Fehlerhaftes Anmeldeproblem im Zusammenhang mit Cookies

8

das wird lang ...

Ich habe einen schlimmen Fall eines fehlerhaften Anmeldefehlers aufgrund einer falschen Cookie-Verwaltung. Zunächst verwalte ich ein geschlossenes Geschäft (B2B), in dem sich Kunden anmelden müssen, bevor sie den Katalog sehen können. Jeder nicht registrierte Zugriff wird auf die Anmeldeseite umgeleitet, aber hin und wieder kann sich der Kunde nicht anmelden, selbst wenn Benutzername und Passwort korrekt sind. Ich sage 'Benutzername', weil ich die Erweiterung Diglin_Username und das StoreRestricition-Plugin verwende, um das gewünschte Verhalten zu erzielen. Was passiert ist, dass ich manchmal zwei verschiedene Sätze von Cookies gefunden habe, die von Magento hinterlassen wurden, und die sich auf zwei verschiedene Domänen beziehen (z. B. www.abc.com und .abc.com).

Nachdem ich diesen Artikel des großen Alan Storm über die Instanziierung früher Sitzungen gelesen und das gefürchtete PHPSESSID-Cookie in meinem Browser gefunden hatte, untersuchte ich das Problem eingehend.

Was ich gefunden habe, ist zweiseitig. Zuerst habe ich einen Mage :: Log () -Aufruf in die Funktion start () in der Mage_Core_Model_Session_Abstract_Varien-Klasse eingefügt, um die verschiedenen Versuche von Magento zu protokollieren, eine neue Sitzung zu starten, und festgestellt, dass nach dem ersten Aufruf von Mage :: run () der preDispatch () Die Methoden dispatch () und postDispatch () der Klasse Mage_Core_Controller_Front_Action werden in der üblichen Reihenfolge aufgerufen. Wenn postDispatch () ausgeführt wird, kann die von preDispatch () gestartete Sitzung jedoch nicht gefunden werden, und es wird eine neue Sitzung erstellt. In dieser Hinsicht habe ich einen Unterschied im Code zwischen Magento 1.7.x und 1.8.x festgestellt, und ich denke, das könnte das Problem möglicherweise beheben:

Magento 1.7.x - Mage_Core_Model_Session_Abstract_Varien Klasse:

public function start($sessionName=null)
{
    if (isset($_SESSION)) {
        return $this;
    }
    .
    .
}

Magento 1.8.x - Klasse Mage_Core_Model_Session_Abstract_Varien:

public function start($sessionName=null)
{
    if (isset($_SESSION) && !$this->getSkipEmptySessionCheck()) {
        return $this;
    }
    .
    .
}

Ich kann jedoch nicht finden, wo die SkipEmptySessionCheck-Eigenschaft festgelegt werden soll, und habe am Ende die Mage_Core_Controller_Front_Action-Klasse auf folgende Weise gepatcht:

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;
}

postDispatch () ruft Mage :: getSingleton ('core / session') nicht auf (das hätte eine neue Sitzung erstellt), wenn keine bereits gestartete Sitzung gefunden werden kann. Bis zum PHPSESSID-Cookie und alles erledigt, dachte ich ...

Aber nicht so. Jetzt habe ich das PHPSESSID-Cookie entfernt, aber immer noch zwei verschiedene Cookies (unregelmäßig) im Browser gespeichert. Wenn ich nur die falschen Cookies lösche, kann ich mich erfolgreich anmelden, oder ich werde ohne Nachricht zur Anmeldeseite weitergeleitet. Ich habe versucht, die Cookie-Domäne explizit in der Systemkonfiguration anzugeben, aber das Problem wurde dadurch nicht behoben.

Wieder tief in der Codebasis, und ich fand heraus, dass an den verschiedenen Stellen, an denen Magento ein Cookie setzt, die Domäne von der Funktion getDomain () in der Klasse Mage_Core_Model_Cookie verwendet werden muss:

public function getDomain()
{
    $domain = $this->getConfigDomain();
    if (empty($domain)) {
        $domain = $this->_getRequest()->getHttpHost();
    }
    return $domain;
}

Wenn Sie sich nun die Seite ansehen, die Sie von Magento in Ihrem Browser erhalten, finden Sie im Abschnitt "Kopf" Folgendes:

<script type="text/javascript">
//<![CDATA[
Mage.Cookies.path     = '/';
Mage.Cookies.domain   = '.www.abc.com';
//]]>
</script>

Diese Zeilen stammen aus app / design / frontend / base / default / template / page / js / cookie.phtml:

<script type="text/javascript">
//<![CDATA[
Mage.Cookies.path     = '<?php echo $this->getPath()?>';
Mage.Cookies.domain   = '<?php echo $this->getDomain()?>';
//]]>
</script>

und dieser Code verweist wiederum auf die Funktion getDomain () in der Klasse Mage_Page_Block_Js_Cookie:

public function getDomain()
{
    $domain = $this->getCookie()->getDomain();
    if (!empty($domain[0]) && ($domain[0] !== '.')) {
        $domain = '.'.$domain;
    }
    return $domain;
}

Wenn ich also die Cookie-Domäne in der Systemkonfiguration auf beispielsweise "www.abc.com" setze, erhalte ich Folgendes:

Mage.Cookies.domain   = '.www.abc.com'

und als ich in meinem Browser sowohl 'www.abc.com' als auch '.www.abc.com' Cookies fand, dachte ich: "Okay, ich setze '.abc.com' in der Systemkonfiguration und werde immer mit 'enden.' .abc.com 'Cookies !! "...

Aber auf keinen Fall. Jetzt bekomme ich auf meiner HTML-Seite immer '.abc.com', aber trotzdem habe ich unregelmäßig ein 'www.abc.com'-Cookie und kein Login.

Ich bin verwirrt und mein Kunde fängt an zu denken, dass ich nicht so gut bin, wie er dachte (ich fange auch an, das zu denken ...) :(

Haben einige von euch (und Mädels) einen Hinweis?

UPDATE: Ich habe jemanden gesehen, der Probleme mit Sitzungen und Cookies mit der Verwendung von Varnish als Cache für Magento in Verbindung gebracht hat. Da ich auch Varnish verwende, werde ich versuchen, das Problem zu beheben, wenn ich es deaktiviere.

Slamarca
quelle
Hallo Marius, warum die Bearbeitung? Verstoße ich gegen eine Forenregel?
Slamarca
Wir sehen dasselbe Verhalten (Login und Kunde verlieren Sitzung), außer dass wir das Problem in keiner Weise reproduzieren können! Dies erschwert jeden Versuch zur Fehlerbehebung, geschweige denn zur Behebung des Problems. Wie haben Sie das Problem zuverlässig repliziert? @Sander Mangel - Das ist genau das Richtige. Ich konnte das Problem nicht reproduzieren, daher kann ich nicht sicher sein, wie die verschiedenen Cookies aussehen. Ich wäre viel glücklicher, wenn ich es reproduzieren könnte, damit ich alle Korrekturen überprüfen kann, die zur Lösung des Problems vorgenommen wurden. Ich hatte gehofft, dass einer von Ihnen mich in die richtige Richtung weisen könnte, wie das Problem reproduziert werden kann. Vielen Dank!
@ Zhulak gleiches Problem mit www. und nicht www. Kekse?
Sander Mangel

Antworten:

8

Dies ist ein Artikel von NovusWeb: http://www.novusweb.com/fix-for-passing-magento-session-ids/

Fix für das Übergeben von Magento-Sitzungs-IDs

Verfasser: Brett Williams

Veröffentlicht am 9. November 2011

Fixieren von Magento-Sitzungs-IDs

Wir verwenden häufig gemeinsam genutzte SSLs beim Erstellen von E-Commerce-Websites. Es ist eine bequeme Möglichkeit, mehrere Geschäfte zu hosten, ohne separate SSL-Zertifikate für jede Site erwerben zu müssen. Die meisten unserer E-Commerce-Kunden verwalten mehrere Geschäfte in einer einzigen Magento- oder OpenCart-Installation. Kürzlich haben wir ein Problem mit Magento festgestellt, bei dem die Sitzungs-ID des Kunden zwischen seinem ersten Besuch auf der Website und seinen Seitenaufrufen nach der Anmeldung im Geschäft als registrierter Kunde nicht erfolgreich übergeben wurde. Magento übergab nicht dieselben Sitzungs-IDs. Dies bedeutete, dass ein Kunde, der sich zuvor angemeldet und Artikel in seinen Warenkorb gelegt hatte, den Inhalt seines Warenkorbs verlieren würde, nachdem er später zurückgekehrt und sich angemeldet hatte. Keine gute Situation.

Beim Betrachten der während einer Sitzung erstellten Cookies stellte ich fest, dass beim Wechsel von einer unsicheren Domäne (dh http: //) zu einer sicheren Domäne (dh https: //) die Sitzungs-ID erfolgreich übergeben wurde und eine neue Das Cookie für die sichere Domäne wurde mit derselben Sitzungs-ID wie die unsichere Domäne erstellt. Als sich der Kunde anmeldete, wurde jedoch ein neues Cookie für die sichere Domäne mit einer völlig neuen Sitzungs-ID erstellt. Magento verwendete jetzt das neuere Cookie. Wenn der Kunde auf eine unsichere Domain-Seite (z. B. Produktdetailseite) klickte, wurde er nicht mehr bei Magento angemeldet, da die unsichere Domain ihre Cookie- / Sitzungs-ID verwendete, nicht die neue Sitzungs-ID beim Anmelden erstellt. Die Lösung wäre, herauszufinden, wo die neue Sitzungs-ID erstellt wurde, und dies zu verhindern.

Also fing ich an, in den Code zu graben, um zu sehen, wo ich herausfinden konnte, wo Magento die neue Sitzung erstellte.

In app / code / core / Mage / Customer / Model / session.php fand ich dies in den Zeilen 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;
}

Meine Lösung bestand darin, die Zeile auskommentieren: $ this-> erneuerSession ():, damit Magento beim Anmelden des Kunden keine neue Sitzung erstellt. Der geänderte Code sieht folgendermaßen aus:

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;
}

Bisher funktioniert bei unseren Tests alles einwandfrei, und die Kundensitzung wird zwischen den Domänen beibehalten. Bevor Sie diese Kerndatei schnell ändern, gehen Sie wie folgt vor:

Sichern Sie Ihre Datenbanken (Sie sollten dies immer tun, bevor Sie Änderungen vornehmen). Erstellen Sie die folgende Verzeichnishierarchie: app / code / local / Mage / Customer / Model /. Legen Sie eine Kopie von session.php in dieses neue Verzeichnis. Kommentieren Sie die oben gezeigte Zeile aus und speichern Sie Ihre Datei. Indem Sie Ihre Änderungen in das Verzeichnis app / code / local einfügen, weisen Sie Magento an, diese Dateien anstelle der Kerndateien zu verwenden. Noch wichtiger ist, dass Sie den Verlust Ihrer Änderungen verhindern, falls Sie Magento in Zukunft aktualisieren.

Es bietet auch eine bequeme Möglichkeit zum Speichern und Verwalten Ihrer Codeänderungen, da Sie nur geänderte Dateien im Verzeichnis app / code / local aufbewahren müssen.

Hinterlassen Sie unbedingt einen Kommentar, wenn Sie eine elegantere Lösung kennen oder wenn Sie feststellen, dass dies für Sie funktioniert oder nicht.

Seanbreeden
quelle
4
Für Änderungen gespeichert in app/code/local/Mage/*. Extrahieren Sie vor dem Magento-Upgrade den Code aus dem Installationsprogramm und vergleichen Sie ihn mit Ihrem geänderten Code, um festzustellen, ob er anders ist. Wenn ja, ändern Sie die neue Version, die nach dem Upgrade eingerichtet werden soll. Es gibt nichts Schöneres, als es beim Upgrade beizubehalten, damit die Site aufgrund inkompatibler Änderungen im Inhalt umfällt.
Fiasco Labs
3
Einverstanden. Dieser Artikel würde ohnehin nur für Installationen vor 1.8 gelten, da sie $this->renewSession();zur setCustomerAsLoggedIn()Funktion verschoben wurden .
Seanbreeden
1
Für aktuellere Magento-Versionen suchen Sie einfach nach "erneuerSession ()" und Sie finden es dort code/core/Mage/Core/Model/Session/Abstract.phpund code/core/Mage/Admin/Model/Session.phpwo es auskommentiert werden kann. Natürlich in einer lokalen Kopie des Modells. @FiascoLabs noch besser, führen Sie eine ordnungsgemäße Überschreibung nur der Funktion, die Sie ändern müssen, und lassen Sie den Rest der Datei im Kern intakt :)
WackGet
1
Dies hat uns geholfen, nachdem wir 4 Jahre später 3 Wochen lang versucht hatten, Fehler zu beheben. Das Problem trat bei uns (Magento 1.9.3.2) auf, als wir Amasty FPC installierten und unseren Server auf Last testeten. dh nicht in der Lage, sich mit Facebook und / oder normalem Login anzumelden, nicht in den Warenkorb zu legen, wenn der Server unter Last ist. Danach manifestierte sich das Problem auch ohne Last. Derzeit scheint das Problem behoben zu sein, nachdem Sie Ihrer Antwort gefolgt sind. Vielen Dank @seanbreeden. Sie haben sehr müden Entwicklern neues Leben eingehaucht. <3
Ali