上篇文章介绍了cookie和session的使用和注意事项
这通常是这样的:当您通过输入用户名和密码登录时,您将被重定向到相同的登录页面和URL,并且您的浏览器附加了nonce id。对于客户前端和Magento后端登录都会发生这种情况。
让我们看看为什么会发生这种情况的几个原因,以及我们应该如何解决这些问题。
原因#1:Cookie域与服务器域不匹配
假设您的Magento站点是,example.com
并且Magento中的cookie域配置为xyz.com
。
在这种情况下,两个Magento cookie都将设置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 * 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:使用了多个子域,Magento的cookie配置不正确
假设您的网站是example.com
。登录example.com/admin
工作正常。
但是,例如staging.example.com/admin
,在您的暂存/质量检查站点上,如果不删除所有cookie,则无法登录。系统可能允许登录staging.example.com
,但是当我们再次登录时example.com/admin
,您的下一次点击会将您staging.example.com
踢回登录页面。使用前端登录的客户也会遇到类似的行为。
解决方案1
选项A:如果您的主域和子域托管在同一台服务器上
- 通过“配置”管理菜单更改Cookie域。根据屏幕截图,转到
System > Configuration > General > Web 。 - 查看Cookie域是否为
example.com
,或者.example.com
(请注意前面的句点)。如果没有,请将其设置为.example.com
。
选项B:如果您的主域和子域托管在不同的服务器上
- 通过“配置”管理菜单更改Cookie域。根据屏幕截图,转到
System > Configuration > General > Web 。 - 查看Cookie域是否
www.example.com
,或.www.example.com
(请注意前面的句点)。如果没有,请将其设置为.www.example.com
。 - 在
test.example.com
商店中,将Cookie域设置.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
文件是否与Magento配置中的cookie域相同 - 如果不将其更改为与Magento配置相同,如下所示:
cookie\_domain = example.com
解决方案3
这不是推荐的方法,但如果所有选项都失败,您可以尝试此代码,通过更改adminhtml
子域的cookie名称来更改选项。复制文件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导致间歇性登录问题
在少数情况下,系统可能会创建多个前端cookie,从而阻止系统允许您登录。
场景1
当您的Magento系统在Magento配置中具有与主域和子域相同的配置时,如果用户登录到这两个站点,Magento会创建两个cookie。一个具有主域的“域值”,另一个具有子域。因此,我们将有两个前端cookie会话,因此我们将无法登录系统。
解
将Cookie域设置更改.example.com
为域和子域配置。
情景2
在这种情况下,我们在你说php.ini
,没有Cookie域配置和Magento的域值的example.com
配置。现在,当用户登录时www.example.com
,系统会创建一个域值为example.com
Magento配置的cookie 。当用户注销时,Magento将使用来自访问的URL(即www.example.com
)的域值重新生成cookie ,因为php.ini
没有指定cookie域。请注意,如果用户使用登录example.com
或配置了cookie域,则php.ini
不会出现任何问题。
解决方案1
在您的php.ini
文件中添加一个与您的Magento配置相同的cookie域。
session.cookie\_domain = example.com
解决方案2
将Cookie域更改.example.com
为域和子域配置。
注意:使用我们的cookieTest.php
脚本来查看您是否有双前端cookie。
原因#4:无法创建(读取)会话ID
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:您的uid不会创建会话数据文件
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
如果要在文件中保存会话,并且文件夹或文件缺少Web服务器用户权限,则会发生此错误。因此,对于nginx,如果您的网络服务器用户是www-data,您需要使用以下方式授予该文件夹的所有权:
sudo chown -R www-data:www-data
解决方案2
如果您在Vagrant上运行,则可能必须确保或更改文件会话路径。
解决方案3
另一个原因是var/sessions
文件夹中可能存在一些旧会话- 删除它们并测试是否可以解决问题。
注意:如果您可以选择使用其他会话提供程序,请切换到另一个。例如,从Redis转到文件。清除var/cache
文件夹并查看其是否有效 - 再次,只在开发环境中尝试此操作。
用于检测Cookie问题的PHP脚本
<?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