Vấn đề đăng nhập liên quan đến cookie thất thường


8

đâ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.


Xin chào Marius, tại sao lại chỉnh sửa? Tôi có phá vỡ một số quy tắc diễn đàn?
slamarca

chúng tôi đang thấy hành vi tương tự (đăng nhập và khách hàng mất phiên), ngoại trừ chúng tôi không thể tái tạo vấn đề theo bất kỳ cách nào! Điều này thực sự làm phức tạp bất kỳ nỗ lực khắc phục sự cố, hãy để một mình giải quyết vấn đề. Làm thế nào bạn đáng tin cậy nhân rộng vấn đề? @Sander Mangel - Đó chỉ là vấn đề, tôi chưa thể tái tạo vấn đề nên tôi không thể chắc chắn các cookie khác nhau trông như thế nào. Tôi sẽ hạnh phúc hơn rất nhiều nếu tôi có thể sao chép nó để tôi có thể xác minh bất kỳ sửa chữa nào được thực hiện để giải quyết vấn đề. Tôi đã hy vọng nếu bất kỳ ai trong số các bạn có thể chỉ cho tôi đi đúng hướng về cách tái tạo vấn đề. Cảm ơn!

@Zhulak cùng một vấn đề với www. và không www. bánh quy?
Sander Mangel

Câu trả lời:


8

Đây là một bài viết từ NovusWeb: http://www.novusweb.com/fix-for-passing-magento-session-ids/

Sửa lỗi để vượt qua ID phiên Magento

Tác giả: Brett Williams

Đăng ngày 9 tháng 11 năm 2011

Sửa ID phiên Magento

Chúng tôi thường sử dụng SSL được chia sẻ khi xây dựng các trang web thương mại điện tử. Đó là một cách thuận tiện để lưu trữ nhiều cửa hàng mà không phải mua chứng chỉ SSL riêng cho từng trang web. Hầu hết các khách hàng thương mại điện tử của chúng tôi quản lý nhiều cửa hàng trong một cài đặt Magento hoặc OpenCart. Gần đây, chúng tôi đã phát hiện sự cố với Magento khi ID phiên của khách hàng không được chuyển thành công giữa lần truy cập ban đầu của họ đến trang web và lượt xem trang của họ sau khi đăng nhập vào cửa hàng với tư cách là khách hàng đã đăng ký. Magento đã không vượt qua cùng một ID phiên và điều này có nghĩa là một khách hàng trước đó đã đăng nhập và thêm các mặt hàng vào giỏ hàng của họ, sẽ mất nội dung trong giỏ hàng của họ sau khi quay lại sau và đăng nhập. Không phải là một tình huống tuyệt vời.

Khi xem xét các cookie được tạo trong một phiên, tôi thấy rằng khi đi từ một miền không an toàn (nghĩa là http: //) sang một miền an toàn (ví dụ: https: //), ID phiên đã được thông qua thành công và mới cookie cho miền an toàn đã được tạo với cùng ID phiên với miền không an toàn. Tuy nhiên, khi khách hàng đăng nhập, một cookie mới đã được tạo cho miền an toàn với ID phiên hoàn toàn mới. Magento hiện đang sử dụng cookie mới hơn và bất cứ khi nào khách hàng nhấp vào để quay lại trang tên miền không an toàn (ví dụ: trang chi tiết sản phẩm), họ không còn đăng nhập vào Magento vì tên miền không an toàn đang sử dụng ID / phiên ID của nó, không phải là mới ID phiên được tạo khi đăng nhập. Giải pháp sẽ là tìm nơi ID phiên mới được tạo và ngăn điều đó xảy ra.

Vì vậy, tôi bắt đầu đào sâu vào mã để xem liệu tôi có thể tìm thấy Magento đang tạo phiên mới ở đâu không.

Trong ứng dụng / mã / lõi / Pháp sư / Khách hàng / Mô hình / session.php, tôi đã tìm thấy điều này ở các dòng 177-189 (Magento CE 1.5.1):

public function login($username, $password)
{
/** @var $customer Mage_Customer_Model_Customer */
$customer = Mage::getModel('customer/customer')
->setWebsiteId(Mage::app()->getStore()->getWebsiteId());

if ($customer->authenticate($username, $password)) {
    $this->setCustomerAsLoggedIn($customer);
    $this->renewSession();
    return true;
}
return false;
}

Giải pháp của tôi là nhận xét dòng: $ this-> refreshSession ():, để Magento sẽ không tạo phiên mới khi khách hàng đăng nhập. Mã thay đổi trông như thế này:

public function login($username, $password)
{
/** @var $customer Mage_Customer_Model_Customer */
$customer = Mage::getModel('customer/customer')
->setWebsiteId(Mage::app()->getStore()->getWebsiteId());

if ($customer->authenticate($username, $password)) {
    $this->setCustomerAsLoggedIn($customer);
    //$this->renewSession();
    return true;
}
return false;
}

Cho đến nay trong thử nghiệm của chúng tôi, mọi thứ đều hoạt động tốt và phiên của khách hàng đang được giữ lại giữa các tên miền. Bây giờ, trước khi bạn vội vàng thay đổi tập tin cốt lõi này, hãy làm như sau:

Sao lưu cơ sở dữ liệu của bạn (bạn phải luôn luôn làm điều này trước khi thực hiện bất kỳ sửa đổi nào). Xây dựng hệ thống phân cấp thư mục sau: app / code / local / Mage / Customer / Model /. Đặt một bản sao của session.php vào thư mục mới này. Nhận xét dòng thích hợp, hiển thị ở trên và lưu tệp của bạn. Bằng cách đặt các sửa đổi của bạn vào thư mục ứng dụng / mã / cục bộ, bạn đang bảo Magento sử dụng các tệp này thay vì các tệp cốt lõi. Quan trọng hơn, bạn đang ngăn chặn việc mất các sửa đổi nếu bạn cập nhật Magento trong tương lai.

Nó cũng cung cấp một cách thuận tiện để lưu trữ và quản lý các sửa đổi mã của bạn, vì bạn chỉ cần giữ các tệp đã sửa đổi trong thư mục ứng dụng / mã / cục bộ.

Hãy chắc chắn để lại nhận xét nếu bạn biết về một giải pháp thanh lịch hơn, hoặc nếu bạn thấy điều này hiệu quả hoặc không hiệu quả với bạn.


4
Đối với sửa đổi được lưu trữ trong app/code/local/Mage/*. Trước khi nâng cấp Magento, hãy trích xuất mã từ trình cài đặt, so sánh với mã sửa đổi của bạn để xem nó có khác không. Nếu vậy sửa đổi phiên bản mới sẽ được đưa vào vị trí sau khi nâng cấp. Không có gì giống như bảo tồn nó khi nâng cấp để trang web bị đổ vì những thay đổi không tương thích trong nội dung.
Phòng thí nghiệm Fiasco

3
Đã đồng ý. Bài viết này sẽ chỉ áp dụng cho các bản cài đặt 1.8 trước vì chúng đã chuyển $this->renewSession();sang setCustomerAsLoggedIn()chức năng.
seanbreeden

1
Để biết thêm các phiên bản Magento hiện tại, chỉ cần tìm kiếm "refreshSession ()" và bạn sẽ tìm thấy nó ở đâu code/core/Mage/Core/Model/Session/Abstract.phpcode/core/Mage/Admin/Model/Session.phpnơi nó có thể được nhận xét. Trong một bản sao địa phương của mô hình, tất nhiên. @FiascoLabs thậm chí còn tốt hơn, thực hiện ghi đè đúng chức năng bạn cần sửa đổi và giữ nguyên phần còn lại của tệp trong lõi :)
WackGet

1
điều này đã giúp chúng tôi ra ngoài sau 3 tuần cố gắng khắc phục sự cố, 4 năm sau. Vấn đề được biểu hiện cho chúng tôi (Magento 1.9.3.2) khi chúng tôi cài đặt FPC Amasty và tải thử nghiệm máy chủ của chúng tôi. tức là không thể đăng nhập bằng facebook và / hoặc đăng nhập bình thường, không thể thêm vào giỏ hàng khi máy chủ đang tải. Sau đó, ngay cả khi không tải, vấn đề được biểu hiện. Bây giờ, hiện tại SEEMS giống như vấn đề được khắc phục sau khi làm theo câu trả lời của bạn. Cảm ơn rất nhiều @seanbreeden. Bạn đã thổi sức sống mới vào các nhà phát triển rất mệt mỏi. <3
ali
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.