Я обнаружил, что всякий раз, когда я перезагружаю Varnish на моем сервере, я теряю сеансы для своих пользователей.
Это очередь заставляет моих клиентов терять свои тележки.
Это нормальное поведение для Varnish или мой VCL виноват? Казалось бы, это не
Дальнейшая информация
При дальнейшем исследовании выясняется, что эта проблема связана с проблемой № 725 на GitHub.
Моя установка Magento - версия 1.9.1.0. Следует также сказать, что весь мой интерфейс работает под https. Я использую Pound перед Varnish для прекращения SSL.
Похоже, что поведение Magento по умолчанию в этой версии заключается в создании вторичного файла cookie внешнего интерфейса, обычно называемого «frontend_cid», в попытке протестировать атаки MITM.
Похоже, что сгенерированный VCL-файл скипидаром не передает этот cookie, что приводит к недействительным сеансам.
Кто-нибудь может объяснить, как файл VCL передает файлы cookie, которые Magento создает для Клиента?
Я сузил это, чтобы Varnish не генерировал требуемые куки.
Начиная с Magento 1.9.1.0, cookie-файл frontend_cid был введен для блокировки MITM-атак.
Это можно найти в Mage_Core_Model_Session_Abstract_Varien
классе, в строке 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);
}
}
Чтобы обеспечить безопасные соединения для клиентов, Varnish должен сгенерировать «внешний» файл cookie, который впоследствии будет использоваться Magento для идентификации конкретного клиента. До сих пор, похоже, это просто отлично. Тем не менее, похоже на Magento 1.9.1.0, теперь ему также необходимо сгенерировать файл cookie frontend_cid.
Varnish должен сделать это, потому что, кэшируя ответ, он также кэширует заголовок ответа, который содержит куки «внешнего интерфейса».
Поэтому по умолчанию Varnish уничтожает все файлы cookie, на которые сервер отвечает, когда обрабатывает условия «поиска» или «прохождения». Это делает это, чтобы несколько пользователей не получали один и тот же кэшированный файл cookie внешнего интерфейса (что могло бы скомпрометировать сеансы пользователей).
В любое время, когда лак обрабатывает запрос с помощью «pipe», Magento может создать необходимые файлы cookie и прикрепить их к браузеру пользователя. Это приводит к тому, что система не проходит первоначальную проверку, но затем предоставляет новый сеанс пользователю. Этот симптом проявляется в потере корзины или невозможности добавить товары в корзину.
Скипидарный VCL будет «передавать» любой запрос, который НЕ имеет тип метода GET или HEAD, как видно из этого кода в vcl_recv
функции:
// 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);
}
Таким образом, этот симптом наиболее заметен, когда пользователь пытается добавить товар в корзину или пытается оформить заказ в первый раз.
Как исправить?
Я полагаю, что решение этой проблемы состоит в том, чтобы Turpentine VCL также создал cookie-файл «frontend_cid» для входящих посетителей, а затем модуль скипидара добавил этот cookie-файл в текущий сеанс, как это делается сейчас для cookie-файла «frontend».
Итак ... как мы это реализуем?
Предостережение: я могу ошибаться, я очень плохо знаком с Varnish, но я потратил много часов на это сейчас, и это то, что я вижу, любая поддержка прямо сейчас будет принята с благодарностью.
ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ И МОЙ ИЗБРАННЫЙ ФИКС - 2015 10 30
Невозможно создать cookie-файл «frontend_cid» на лаке, так как он случайно создается на сервере Magento и сохраняется в виде хеша MD5 в сеансе клиентов. Это мешает вам создавать внешне вне сеанса клиентов.
Лучшее решение, которое я придумал по этому вопросу, - это вместо этого переписать способ, которым Magento обрабатывает сессии клиентов.
В настоящее время Magento обрабатывает недопустимые сеансы, например:
IF
The requested session by the customer is flagged as invalid
THEN
Stop processing request
Redirect to the appropriate page
Моя новая логика выглядит следующим образом:
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
Мой новый подход позволяет лакированно реагировать на запросы клиентов даже при первом посещении. Что не так, как работает последняя реализация скипидара.
My Issue, Issue # 829 - / nexcess / magento-turpentine / Issues / 829 на GitHub. Копию моего VCL можно найти здесь.
Моя проблема на GitHub была закрыта, так как это дубликат гораздо более старой проблемы, найденной здесь: