Estou descobrindo que, sempre que reinicio o Varnish no meu servidor, estou perdendo minhas sessões para meus usuários.
É a vez de fazer meus clientes perderem seus carrinhos de compras.
Esse comportamento é normal para o verniz ou o meu VCL é o culpado? Parece que não é
Mais informações.
Em uma investigação mais aprofundada, parece que esse problema está relacionado ao problema nº 725 no GitHub.
Minha instalação do Magento é a versão 1.9.1.0. Também deve ser dito que todo o meu front-end está sendo executado em https. Estou usando Libra na frente do Varnish para finalizar o SSL.
Parece que o comportamento padrão do Magento nesta versão é criar um cookie secundário de front-end, geralmente chamado de 'frontend_cid'. Na tentativa de testar contra ataques MITM.
Parece que o arquivo VCL gerado pelo Turpentine não está transmitindo esse cookie, o que está causando sessões inválidas.
Alguém pode explicar como o arquivo VCL passa os cookies que o Magento cria para o cliente?
Eu reduzi isso para o Varnish, não gerando os cookies necessários.
A partir do Magento 1.9.1.0, um cookie 'frontend_cid' foi introduzido para bloquear ataques MITM.
Isso pode ser encontrado na Mage_Core_Model_Session_Abstract_Varien
classe, na linha 135
if (Mage::app()->getFrontController()->getRequest()->isSecure() && empty($cookieParams['secure'])) {
// secure cookie check to prevent MITM attack
$secureCookieName = $sessionName . '_cid';
if (isset($_SESSION[self::SECURE_COOKIE_CHECK_KEY])
&& $_SESSION[self::SECURE_COOKIE_CHECK_KEY] !== md5($cookie->get($secureCookieName))
) {
session_regenerate_id(false);
$sessionHosts = $this->getSessionHosts();
$currentCookieDomain = $cookie->getDomain();
foreach (array_keys($sessionHosts) as $host) {
// Delete cookies with the same name for parent domains
if (strpos($currentCookieDomain, $host) > 0) {
$cookie->delete($this->getSessionName(), null, $host);
}
}
$_SESSION = array();
}
if (!isset($_SESSION[self::SECURE_COOKIE_CHECK_KEY])) {
$checkId = Mage::helper('core')->getRandomString(16);
$cookie->set($secureCookieName, $checkId, null, null, null, true);
$_SESSION[self::SECURE_COOKIE_CHECK_KEY] = md5($checkId);
}
}
Para fornecer conexões seguras para os clientes, o Varnish precisa gerar um cookie 'frontend', que o Magento mais tarde usará para identificar esse cliente em particular. Até agora, parece fazer isso muito bem. No entanto, parece que a partir do Magento 1.9.1.0, agora ele também precisa gerar o cookie 'frontend_cid'.
O Varnish precisa fazer isso porque, ao armazenar em cache a resposta, ele também armazena em cache o cabeçalho da resposta, que contém os cookies 'frontend'.
Portanto, por padrão, o Varnish descarta todos os cookies com os quais o back-end responde quando ele manipula as condições de 'consulta' ou 'aprovação'. Isso é feito para impedir que vários usuários sejam emitidos com o mesmo cookie de front-end em cache (que comprometeria as sessões das pessoas).
Sempre que o verniz lida com a solicitação com 'pipe', o Magento pode criar os cookies necessários e anexá-los ao navegador do usuário. Isso resulta no sistema falhando na validação inicial, mas fornecendo uma nova sessão ao usuário. Esse sintoma se manifesta como uma perda de carrinho ou a incapacidade de adicionar produtos ao carrinho de compras.
O Turpentine VCL 'encaminhará' qualquer solicitação que NÃO seja do tipo GET ou HEAD do método, como visto por este código na vcl_recv
função:
// We only deal with GET and HEAD by default
// we test this here instead of inside the url base regex section
// so we can disable caching for the entire site if needed
if (!true || req.http.Authorization ||
req.request !~ "^(GET|HEAD)$" ||
req.http.Cookie ~ "varnish_bypass=1") {
return (pipe);
}
Portanto, o sintoma é mais perceptível quando o usuário tenta adicionar um item ao carrinho ou tenta fazer o checkout pela primeira vez.
Como consertar?
Acredito que a solução para esse problema é fazer com que o Turpentine VCL também crie um cookie 'frontend_cid' para os visitantes recebidos e, em seguida, faça com que o módulo turpentine adicione esse cookie à sessão atual, como agora faz com o cookie 'frontend'.
Então ... como implementamos isso?
Advertência: Eu posso estar errado, sou muito novo no Varnish, mas passei muitas horas nisso agora e é isso que estou vendo, qualquer pessoa que esteja apoiando agora seria muito apreciada.
ATUALIZAÇÃO FINAL E MINHA CORREÇÃO ESCOLHIDA - 2015 10 30
É impossível criar um cookie 'frontend_cid' em verniz, pois o cookie é criado aleatoriamente no servidor pelo Magento e armazenado como um hash MD5 na sessão de clientes. Isso impede que você crie externamente fora da sessão do cliente.
A melhor solução que encontrei nessa questão é substituir a maneira como o Magento lida com as sessões dos clientes.
Atualmente, o Magento lida com sessões inválidas como esta:
IF
The requested session by the customer is flagged as invalid
THEN
Stop processing request
Redirect to the appropriate page
Minha nova lógica é a seguinte:
IF
The requested session by the customer is flagged as invalid
THEN
Create a new session
Complete the requested task
Redirect to the appropriate page
Minha nova abordagem permite envernizada para lidar com a resposta dos clientes mesmo na primeira visita. Não é assim que funciona a mais recente implementação de terebintina.
Minha Edição, Edição 829 - / nexcess / magento-aguarrás / edições / 829 no GitHub. Uma cópia da minha VCL pode ser encontrada aqui.
Meu problema no GitHub foi encerrado, pois é uma duplicata de um problema muito mais antigo encontrado aqui: