Эта статья была создана в сотрудничестве с Ktree . Спасибо за поддержку партнеров, которые делают возможным использование SitePoint.
В этой статье мы рассмотрим, как файлы cookie Magento могут создавать проблемы с функциональностью входа в систему как клиентского, так и административного интерфейса, причину, по которой это происходит, и способы ее устранения.
Это также называется проблемой зацикливания, поскольку экран перенаправляется на тот же экран, даже если имя пользователя и пароль верны.
В конце статьи приведен сценарий, который может помочь выявить некоторые проблемы. Не стесняйтесь использовать и изменять в соответствии с вашими потребностями.
Что такое печенье?
Файл cookie — это фрагмент текста, который веб-сервер может хранить на жестком диске пользователя, а затем может впоследствии извлечь его. Magento использует файлы cookie в функциях Cart & Backend Admin, и они могут стать источником нескольких проблем при невозможности входа в Magento.
Что такое сессия?
Сеанс — это переменная массива на стороне сервера, которая хранит информацию, которая будет использоваться на нескольких страницах. Например, элементы, добавленные в корзину, обычно сохраняются в сеансах, а когда пользователь просматривает страницу оформления заказа, они считываются из сеанса.
Сессии идентифицируются по уникальному идентификатору. Его имя меняется в зависимости от языка программирования — в PHP это называется «PHP Session ID». Как вы уже догадались, тот же ID Session ID должен быть сохранен в виде куки в клиентском браузере для связи.
Хранилище сессий Magento
Magento может хранить сеансы через нескольких поставщиков сеансов, и это можно настроить в файле конфигурации Magento по адресу app/etc/local.xml
. Эти поставщики сеансов могут быть выбраны здесь.
файл
<session_save><![CDATA[files]]></session_save> <session_save_path> <![CDATA[/tmp/session]]> </session_save_path>
База данных
Разрешение сеансов сохранять себя в базе данных выполняется в /app/etc/local.xml
путем добавления <session_save><![CDATA[db]]></session_save>
.
Приложения Magento хранят сеансы в таблице Core\_session
.
Redis
<session_save>db</session_save> <redis_session> <host>127.0.0.1</host> <port>6379</port> </redis_session>
MemCache
session_save><![CDATA[memcache]]></session_save> <session_save_path> <![CDATA[tcp://localhost:11211?persistent=1&weight=2&timeout=10&retry_interval=10]]> </session_save_path>
Использование Magento
Magento использует два разных файла cookie с именами «frontend» и «adminhtml». Первая создается при просмотре любой страницы. Этот файл cookie также обновляется всякий раз, когда клиент входит в систему, а следующий создается при входе внутреннего пользователя. Вы можете проверить, были ли созданы файлы cookie, нажав Inspect Element> Application , как показано на рисунке ниже (из Chrome ):
Файлы cookie настраиваются в Magento через меню администратора «Конфигурация» — « Система»> «Конфигурация»> «Общие»> «Интернет» .
Проблема: Ошибка входа и перенаправления на страницу входа
Если вы не сталкивались с этой проблемой, значит, вы недостаточно долго работали с Magento!
Обычно так и происходит: когда вы входите в систему, вводя свое имя пользователя и пароль, вы будете перенаправлены на ту же страницу входа и URL, а ваш браузер будет добавлен с nonce id. Это происходит как для клиентского интерфейса, так и для фонового входа Magento.
Давайте рассмотрим несколько причин, почему это происходит, и как мы должны решить эти проблемы.
Причина № 1: Домен cookie не соответствует домену сервера
Допустим, ваш Magento-сайт — example.com
а домен cookie в Magento настроен как xyz.com
.
В этом сценарии оба куки-файла Magento установят Domain Value
как xyz.com
, но для проверки сеанса Magento рассмотрит домен, через который был осуществлен доступ к сайту — в данном случае example.com
. Поскольку он не сможет найти активный сеанс со значением домена example.com
, он перенаправит пользователя на страницу входа в систему, даже если предоставлены действительные учетные данные.
app/code/core/Mage/Core/Model/Session/Abstract.php
После входа в систему или выхода из системы система Magento сгенерирует сессию, используя следующий скрипт:
public function renewSession() { $this->getCookie()->delete($this->getSessionName()); $this->regenerateSessionId(); $sessionHosts = $this->getSessionHosts(); $currentCookieDomain = $this->getCookie()->getDomain(); if (is_array($sessionHosts)) { foreach (array_keys($sessionHosts) as $host) { // Delete cookies with the same name for parent domains if (strpos($currentCookieDomain, $host) > 0) { $this->getCookie()->delete($this->getSessionName(), null, $host); } } } return $this; }
app/code/core/Mage/Core/Model/Session/Abstract/Varien.php
Magento проверит сессию для каждого запроса следующим способом:
public function init($namespace, $sessionName=null) { if (!isset($_SESSION)) { $this->start($sessionName); } if (!isset($_SESSION[$namespace])) { $_SESSION[$namespace] = array(); } $this->_data = &$_SESSION[$namespace]; $this->validate(); $this->revalidateCookie(); return $this; }
Обычно вы можете видеть это, когда вы переносите свой экземпляр Magento из одного домена в другой домен, например из производства в промежуточный, и забыли изменить домен cookie.
Примечание: вы можете запустить предоставленный скрипт cookieTest.php
, который проверяет, что является доменным файлом cookie сервера и что установлено в конфигурации Magento.
Решение:
Измените Cookie-домен через меню администратора конфигурации. Перейдите в System> Configuration> General> Web , как показано на скриншоте.
В качестве альтернативы вы можете изменить это, запустив эти SQL-запросы.
Для проверки домена cookie используйте этот запрос select для получения конфигурации:
SELECT * FROM core_config_data WHERE path = 'web/cookie/cookie_domain';
После выполнения этого запроса мы получим результаты. Убедитесь, что столбец ‘value’ совпадает с вашим доменом. Обновите значение, если оно не совпадает с вашим доменом.
Чтобы обновить домен cookie, используйте этот запрос:
UPDATE core_config_data SET VALUE = "domain.com" WHERE path = 'web/cookie/cookie_domain';
Причина № 2: используется несколько поддоменов, и неверная конфигурация файлов cookie в Magento
Допустим, ваш сайт — example.com
. Вход в example.com/admin
работает нормально.
Но на вашем промежуточном / QA-сайте, например staging.example.com/admin
, вы не можете войти без удаления всех файлов cookie. Система может разрешить вход в систему на staging.example.com
, но когда мы снова staging.example.com
сайт example.com/admin
, ваш следующий щелчок на staging.example.com
вас на страницу входа. Аналогичное поведение наблюдается и для клиентов, использующих интерфейсный вход в систему.
Решение 1
Вариант A: если ваш основной домен и субдомены размещены на одном сервере
- Измените Cookie-домен через меню администратора конфигурации. Перейдите в System> Configuration> General> Web , как показано на скриншоте.
- Посмотрите, является ли Cookie-домен доменом
example.com
или.example.com
(обратите внимание на период впереди). Если нет, установите.example.com
.
Вариант Б: если ваш основной домен и субдомены размещены на разных серверах
- Измените Cookie-домен через меню администратора конфигурации. Перейдите в System> Configuration> General> Web , как показано на скриншоте.
- Посмотрите, является ли домен
.www.example.com
www.example.com
или.www.example.com
(обратите внимание на период впереди). Если нет, установите его на.www.example.com
. - В магазине
test.example.com
установите для домена.test.example.com
в тестовой среде.
Или измените это, запустив эти sql запросы.
Для проверки домена cookie используйте следующий запрос select для получения конфигурации:
SELECT * FROM core_config_data WHERE path = 'web/cookie/cookie_domain';
После выполнения вышеуказанного запроса мы получим результаты. Убедитесь, что столбец «значение» совпадает с вашим доменом или нет. Обновите значение, если оно не совпадает с вашим доменом.
Для обновления домена cookie используйте следующий запрос:
UPDATE core_config_data SET VALUE = "domain.com" WHERE path = 'web/cookie/cookie_domain';
Решение 2
Проверьте, имеет ли ваш файл php.ini
тот же домен cookie, что и в вашей конфигурации Magento, если не измените его на тот же, что и в конфигурации Magento, как показано ниже:
cookie\_domain = example.com
Решение 3
Это не рекомендуемый подход, но если все параметры не удаются, вы можете попробовать этот код, изменив параметр, изменив adminhtml
cookie adminhtml
для поддоменов. Скопируйте файл action.php
и сохраните его в том же пути к папке, что и локальный, чтобы ваш основной файл кода можно было переопределить.
В файл app/code/core/Mage/Core/Controller/Varien/Action.php
необходимо внести два изменения.
В функции preDispatch
измените эти строки:
/** @var $session Mage_Core_Model_Session */ $session = Mage::getSingleton('core/session', array('name' => $this->_sessionNamespace))->start();
Для того, чтобы:
$namespace = $this->_sessionNamespace.($_SERVER['SERVER_NAME']=='subdomain.example.com'?'_subdomain':''); /** @var $session Mage_Core_Model_Session */ $session = Mage::getSingleton('core/session', array('name' => $namespace))->start();
В функции setRedirectWithCookieCheck
измените:
/** @var $session Mage_Core_Model_Session */ session = Mage::getSingleton('core/session', array('name' => $this->_sessionNamespace));
Для того, чтобы:
$namespace = $this->_sessionNamespace.($_SERVER['SERVER_NAME']=='subdomain.example.com'?'_subdomain':''); /** @var $session Mage_Core_Model_Session */ $session = Mage::getSingleton('core/session', array('name' => $namespace));
После этого найдите следующий текст во всех файлах:
Mage::getSingleton('core/session', array('name' => 'adminhtml'));`
Если обнаружены какие-либо случаи, замените их на:
Mage::getSingleton('core/session', array('name' => 'adminhtml'.($_SERVER['SERVER_NAME']=='subdomain.example.com'?'_subdomain':'')));
Причина № 3: Двойные входные куки-файлы, вызывающие периодические проблемы со входом
В некоторых сценариях существует возможность создания системой нескольких файлов cookie, что не позволяет системе войти в систему.
Сценарий 1
Если ваша система Magento имеет одинаковую конфигурацию для вашего основного домена и субдомена в конфигурации Magento, и если пользователь входит на оба сайта, Magento создает два файла cookie. Один имеет значение «Доменное значение» с основным доменом, а другой с поддоменом. Таким образом, у нас будет два сеанса cookie-файлов, поэтому мы не сможем войти в систему.
Решение
Измените настройку Cookie Domain на .example.com
для конфигурации домена и субдомена.
Сценарий 2
В этом сценарии, скажем, в вашем php.ini
домен cookie не настроен, а значение домена Magento на example.com
настроено. Теперь, когда пользователь входит в систему через www.example.com
, система создает файл cookie со значением значения домена example.com
из конфигурации Magento. Когда пользователь выходит из системы, Magento сгенерирует файл cookie со значением домена по URL-адресу, к которому был получен доступ (например, www.example.com
), поскольку в php.ini
домен cookie не был указан. Обратите внимание, что если пользователь входит в систему с помощью example.com
или в файле php.ini
настроен домен cookie, проблем не возникает.
Решение 1
Добавьте домен cookie в ваш файл php.ini
который совпадает с вашим конфигом Magento.
session.cookie\_domain = example.com
Решение 2
Измените Домен .example.com
на .example.com
для конфигурации домена и субдомена.
Примечание. Используйте наш скрипт cookieTest.php
чтобы узнать, есть ли у вас файлы cookie с двойным интерфейсом.
Причина № 4: Не удалось создать (прочитать) идентификатор сеанса
Recoverable Error: session\_regenerate\_id(): Failed to create(read) session ID: user (path: /var/lib/php/sessions) in app/code/core/Mage/Core/Model/Session/Abstract/Varien.php on line 492
Это ошибка, которую вы можете увидеть в журнале исключений, и она может возникнуть только для PHP7, так как PHP7 выполняет строгую проверку типов.
Решением для этого является изменение функции чтения ядра Magento путем приведения типов. Подробнее об этом здесь .
public function read($sessId) { //return $data; return (string)$data; }
Причина № 5: Файл данных сеанса не создан вашим пользователем
Warning: session_start(): Session data file is not created by your uid in app/code/core/Mage/Core/Model/Session/Abstract/Varien.php on line 125
Решение 1
Эта ошибка возникает, если вы сохраняете сеансы в файлах, а папка или файлы не имеют разрешения пользователя веб-сервера. Так, в случае nginx, если пользователь вашего веб-сервера — www-data, вам нужно предоставить право владения папке, используя:
sudo chown -R www-data:www-data
Решение 2
Если вы работаете в Vagrant, вам может потребоваться убедиться или изменить путь к файлу сессии.
Решение 3
Другая причина в том, что в папке var/sessions
могут быть старые сеансы — удалите их и проверьте, решает ли это проблему.
Примечание. Если у вас есть возможность использовать других поставщиков сеансов, переключитесь на другого. Например, перейти от Redis к файлу. Очистите папку var/cache
и посмотрите, работает ли она — и снова, попробуйте только это в вашей среде разработки.
Скрипт PHP для обнаружения проблем с cookie
<?php ini_set('display_errors', 1); $mageFileName = getcwd() . '/app/Mage.php'; require $mageFileName; Mage::app(); echo "<b> Server Cookie Domain Configuration : </b> ".ini_get('session.cookie_domain')."<br>"; foreach (Mage::app()->getStores() as $store) { echo "<b>" . $store->getName() . "</b><br>"; $configCookieDomain = Mage::getStoreConfig('web/cookie/cookie_domain', $store->getId()); $storeConfigUrl = Mage::getStoreConfig('web/unsecure/base_url', $store->getId()); $sourceUrl = parse_url($storeConfigUrl); $storeDomain = $sourceUrl['host']; $cookieDomainResult = ($configCookieDomain == $storeDomain || $configCookieDomain == '.' . $storeDomain) ? "" : "not"; echo "Config cookie Domain : " . $configCookieDomain . " and Store Domain: " . $storeDomain . " " . $cookieDomainResult . " configured properly<br>"; } //echo "<b>Request Cookies:</b> "; $requestCookie = Mage::app()->getRequest()->getHeader('cookie'); $requestCookieArr = explode(';', $requestCookie); $sessionIds = array(); foreach ($requestCookieArr as $requestCookieItem) { $cookieValue = explode('=', $requestCookieItem); // echo $requestCookieItem."<br>"; if (trim($cookieValue[0]) == 'frontend' || trim($cookieValue[0]) == 'adminhtml') { $cookieName = trim($cookieValue[0]); $sessionId = trim($cookieValue[1]); $sessionIds[$cookieName][] = $sessionId; } } $areas = array("frontend", "adminhtml"); foreach ($areas as $area => $cookieName) { echo "<b>validating " . $cookieName . " cookie </b><br>"; $cookieExpires = Mage::getModel('core/cookie')->getLifetime($cookieName); $cookiePath = Mage::getModel('core/cookie')->getPath($cookieName); $cookieDomain = Mage::getModel('core/cookie')->getDomain($cookieName); $cookieSecure = Mage::getModel('core/cookie')->isSecure($cookieName); $cookieHttpOnly = Mage::getModel('core/cookie')->getHttponly($cookieName); echo "Cookie Lifetime : " . $cookieExpires . " <br>"; echo "Cookie Path : " . $cookiePath . " <br>"; echo "Cookie Domain : " . $cookieDomain . " <br>"; echo "Cookie Is Secure : " . $cookieSecure . " <br>"; echo "Cookie Httponly : " . $cookieHttpOnly . " <br>"; if (count($sessionIds[$cookieName]) > 1) { echo "<span style='color:red'><b>We have " . count($sessionIds[$cookieName]) . " " . $cookieName . " Cookies with values : </b>" . implode(',', $sessionIds[$cookieName]) . "<br>"; //$encryptedSessionId = Mage::getSingleton("core/session")->getEncryptedSessionId(); $encryptedSessionId = Mage::getModel('core/cookie')->get($cookieName); echo "Original Cookie value : " . $encryptedSessionId . "<br>"; echo "Please verify the Subdomain and Main Site Cookie Domain Configuration</span><br>"; } } ?>
Выход:
Magento Store EN Config cookie Domain : staging.abc.com and Store Domain: staging.abc.com configured properly Magento Store FR Config cookie Domain : staging.abc.com and Store Domain: staging.abc.com configured properly validating frontend cookie Cookie Lifetime : 31536000 Cookie Path : / Cookie Domain : staging.zeb.be Cookie Is Secure : Cookie Httponly : 1 validating adminhtml cookie Cookie Lifetime : 31536000 Cookie Path : / Cookie Domain : staging.zeb.be Cookie Is Secure : Cookie Httponly : 1