đây sẽ là một ...
Tôi đã gặp phải một trường hợp xấu về lỗi đăng nhập thất thường, do quản lý cookie sai. Trước hết, tôi đang quản lý một cửa hàng đóng (B2B) trong đó khách hàng phải đăng nhập trước khi họ có thể xem danh mục. Mọi quyền truy cập chưa đăng ký sẽ được chuyển hướng đến trang đăng nhập, nhưng thỉnh thoảng khách hàng không thể đăng nhập ngay cả khi tên người dùng và mật khẩu là chính xác. Tôi nói 'tên người dùng' vì tôi sử dụng tiện ích mở rộng Diglin_Username và plugin StoreRestricition để đạt được hành vi mong muốn. Điều xảy ra là đôi khi tôi tìm thấy hai bộ cookie khác nhau do Magento để lại và chúng đề cập đến hai tên miền khác nhau (ví dụ: .www.abc.com và .abc.com).
Sau khi đọc bài viết này từ Alan Storm tuyệt vời về khởi tạo phiên đầu tiên và tìm thấy cookie PHPSESSID đáng sợ trong trình duyệt của tôi, tôi đã tìm hiểu sâu về vấn đề này.
Những gì tôi tìm thấy là hai mặt. Đầu tiên tôi đặt một lệnh gọi Mage :: Log () trong hàm start () trong lớp Mage_Core_Model_Session_Abauge_Varien để ghi lại các nỗ lực khác nhau được thực hiện bởi Magento để bắt đầu một phiên mới và nhận thấy rằng sau Mage :: run () đầu tiên gọi hàm preDispatch () , các phương thức điều phối () và postDispatch () của lớp Mage_Core_Controll_Front_Action được gọi theo trình tự thông thường nhưng dường như khi postDispatch () thực thi, nó không thể tìm thấy phiên bắt đầu bởi preDispatch () và tiến hành tạo phiên mới. Về vấn đề này, tôi đã tìm thấy một sự khác biệt trong mã giữa phiên bản Magento 1.7.x và 1.8.x và tôi nghĩ rằng có thể giải quyết vấn đề:
Magento 1.7.x - Lớp Mage_Core_Model_Session_Abauge_Varien:
public function start($sessionName=null)
{
if (isset($_SESSION)) {
return $this;
}
.
.
}
Magento 1.8.x - Lớp Mage_Core_Model_Session_Abauge_Varien:
public function start($sessionName=null)
{
if (isset($_SESSION) && !$this->getSkipEmptySessionCheck()) {
return $this;
}
.
.
}
Tôi chỉ không thể tìm thấy nơi để đặt thuộc tính SkipEmptySessionCheck, vì vậy tôi đã kết thúc việc vá lớp Mage_Core_Controll_Front_Action theo cách này:
public function postDispatch()
{
parent::postDispatch();
if (!$this->getFlag('', self::FLAG_NO_START_SESSION )) {
if (session_id()) {
Mage::getSingleton('core/session')->setLastUrl(Mage::getUrl('*/*/*', array('_current'=>true)));
}
}
return $this;
}
để có postDispatch () không gọi Mage :: getSingleton ('core / session') (điều đó sẽ tạo ra một phiên mới) nếu nó không thể tìm thấy một phiên đã bắt đầu. Quá lâu để cookie PHPSESSID và tất cả đã được thực hiện, tôi nghĩ ...
Nhưng không phải vậy. Bây giờ tôi đã thoát khỏi cookie PHPSESSID nhưng vẫn goto hai bộ cookie khác nhau (thất thường) được lưu trong trình duyệt. Chỉ xóa các cookie sai tôi mới có thể đăng nhập thành công hoặc tôi được chuyển hướng đến trang đăng nhập mà không cần một tin nhắn. Tôi đã cố gắng nêu rõ tên miền cookie trong cấu hình hệ thống nhưng điều này không giải quyết được vấn đề.
Đi sâu vào codebase một lần nữa và tôi thấy rằng ở những nơi khác nhau khi Magento đặt cookie, nó sẽ lấy tên miền để sử dụng từ hàm getDomain () trong lớp Mage_Core_Model_Cookie:
public function getDomain()
{
$domain = $this->getConfigDomain();
if (empty($domain)) {
$domain = $this->_getRequest()->getHttpHost();
}
return $domain;
}
Bây giờ, nếu bạn nhìn vào trang bạn nhận được từ Magento trong trình duyệt của mình, bạn có thể tìm thấy trong phần 'đầu' giống như thế này:
<script type="text/javascript">
//<![CDATA[
Mage.Cookies.path = '/';
Mage.Cookies.domain = '.www.abc.com';
//]]>
</script>
Những dòng này đến từ ứng dụng / thiết kế / frontend / cơ sở / mặc định / mẫu / trang / js / cookie.phtml:
<script type="text/javascript">
//<![CDATA[
Mage.Cookies.path = '<?php echo $this->getPath()?>';
Mage.Cookies.domain = '<?php echo $this->getDomain()?>';
//]]>
</script>
và đến lượt mã này tham chiếu hàm getDomain () trong lớp Mage_Page_Block_Js_Cookie:
public function getDomain()
{
$domain = $this->getCookie()->getDomain();
if (!empty($domain[0]) && ($domain[0] !== '.')) {
$domain = '.'.$domain;
}
return $domain;
}
Vì vậy, nếu tôi đặt tên miền cookie trong cấu hình hệ thống, ví dụ: 'www.abc.com' thì tôi kết thúc bằng:
Mage.Cookies.domain = '.www.abc.com'
và tìm thấy trong trình duyệt của tôi cả cookie 'www.abc.com' và '.www.abc.com' tôi nghĩ, "ok, tôi sẽ đặt '.abc.com' trong cấu hình hệ thống và sẽ luôn kết thúc bằng ' .abc.com 'cookie !! "...
Nhưng không có cách nào. Bây giờ trong trang HTML của tôi, tôi luôn nhận được '.abc.com' nhưng dù sao tôi vẫn nhận được cookie 'www.abc.com' và không đăng nhập.
Tôi hoang mang, và khách hàng của tôi bắt đầu nghĩ rằng tôi không tốt như anh ta nghĩ (tôi cũng bắt đầu nghĩ vậy ...) :(
Một số bạn (và các cô gái) có một số gợi ý?
CẬP NHẬT: Tôi đã thấy ai đó liên quan đến các vấn đề với phiên và cookie về việc sử dụng Varnish làm bộ đệm cho Magento. Vì tôi đang sử dụng Varnish nên tôi sẽ thử nếu vô hiệu hóa nó, vấn đề có thể được giải quyết.