Problema di accesso irregolare relativo ai cookie


8

questo sarà lungo ...

Ho un brutto caso di errore di accesso irregolare, a causa della gestione errata dei cookie. Prima di tutto, gestisco un negozio chiuso (B2B) in cui i clienti devono accedere prima di poter vedere il catalogo. Ogni accesso non registrato viene reindirizzato alla pagina di accesso, ma di tanto in tanto il cliente non può accedere anche se nome utente e password sono corretti. Dico "nome utente" perché utilizzo l'estensione Diglin_Username e il plug-in StoreRestricition per ottenere il comportamento desiderato. Quello che succede è che a volte ho trovato due diversi set di cookie lasciati da Magento e si riferiscono a due domini diversi (.www.abc.com e .abc.com per esempio).

Dopo aver letto questo articolo del grande Alan Storm sulla prima istanza della sessione e aver trovato il temuto cookie PHPSESSID nel mio browser, ho approfondito il problema.

Quello che ho trovato è bifronte. Per prima cosa ho inserito una chiamata Mage :: Log () nella funzione start () nella classe Mage_Core_Model_Session_Abstract_Varien per registrare i vari tentativi fatti da Magento per avviare una nuova sessione e ho notato che dopo la prima chiamata Mage :: run () il preDispatch () , i metodi dispatch () e postDispatch () della classe Mage_Core_Controller_Front_Action vengono richiamati nella consueta sequenza ma sembra che quando postDispatch () viene eseguito, non riesca a trovare la sessione avviata da preDispatch () e procede alla creazione di una nuova sessione. A questo proposito ho trovato una differenza nel codice tra Magento 1.7.xe la versione 1.8.x e penso che forse potremmo occuparci del problema:

Magento 1.7.x - Classe Mage_Core_Model_Session_Abstract_Varien:

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

Magento 1.8.x - Classe Mage_Core_Model_Session_Abstract_Varien:

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

Non riesco proprio a trovare dove impostare la proprietà SkipEmptySessionCheck, quindi ho finito per patchare la classe Mage_Core_Controller_Front_Action in questo modo:

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

avere postDispatch () che non chiama Mage :: getSingleton ('core / session') (che avrebbe creato una nuova sessione) se non riuscisse a trovare una sessione già avviata. Così tanto tempo per il cookie PHPSESSID e tutto fatto, ho pensato ...

Ma non è così. Ora mi sono liberato dei cookie di PHPSESSID ma ho comunque trovato due diversi set di cookie (erroneamente) salvati nel browser. Solo cancellando i cookie sbagliati posso accedere con successo, o vengo reindirizzato alla pagina di accesso senza nemmeno un messaggio. Ho provato a dichiarare esplicitamente il dominio dei cookie nella configurazione del sistema, ma questo non ha risolto il problema.

Nel profondo della base di codice di nuovo, e ho scoperto che nei vari punti in cui Magento imposta un cookie ci vuole il dominio da usare dalla funzione getDomain () nella classe Mage_Core_Model_Cookie:

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

Ora, se guardi la pagina che ricevi da Magento nel tuo browser, puoi trovare nella sezione 'head' qualcosa del genere:

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

Queste linee provengono da 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>

e a sua volta questo codice fa riferimento alla funzione getDomain () nella classe Mage_Page_Block_Js_Cookie:

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

Quindi, se imposto il dominio dei cookie nella configurazione del sistema come, ad esempio, "www.abc.com", finisco con:

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

e trovando nel mio browser entrambi i cookie "www.abc.com" e ".www.abc.com" ho pensato "ok, imposterò" .abc.com "nella configurazione del sistema e finirò sempre con" .abc.com 'cookies !! "...

Ma niente da fare. Ora nella mia pagina HTML ricevo sempre ".abc.com", ma ho comunque erroneamente ricevuto un cookie "www.abc.com" e nessun accesso.

Sono perplesso e il mio cliente sta iniziando a pensare che non sono così bravo come pensava (lo sto iniziando a pensare anch'io ...) :(

Alcuni di voi ragazzi (e ragazze) hanno qualche suggerimento?

AGGIORNAMENTO: Ho visto qualcuno riferire problemi con sessioni e cookie all'uso di Varnish come cache per Magento. Dato che sto usando anche Varnish, proverò se disabilitandolo il problema può essere risolto.


Ciao Marius, perché la modifica? Sto infrangendo alcune regole del forum?
slamarca,

stiamo riscontrando lo stesso comportamento (login e cliente perde sessione), tranne per il fatto che non possiamo riprodurre il problema in alcun modo! Questo complica davvero qualsiasi tentativo di risoluzione dei problemi, per non parlare della risoluzione del problema. Come hai replicato in modo affidabile il problema? @Sander Mangel - Questa è la cosa giusta, non sono stato in grado di riprodurre il problema, quindi non posso essere sicuro di come siano i diversi cookie. Sarei molto più felice se riesco a riprodurlo in modo da poter verificare qualsiasi correzione apportata per risolvere il problema. Speravo che qualcuno di voi potesse indicarmi la giusta direzione su come riprodurre il problema. Grazie!

@Zhulak stesso problema con www. e non www. biscotti?
Sander Mangel

Risposte:


8

Questo è un articolo di NovusWeb: http://www.novusweb.com/fix-for-passing-magento-session-ids/

Correzione per il passaggio degli ID sessione Magento

Autore: Brett Williams

Pubblicato il 9 novembre 2011

Correzione degli ID sessione Magento

Spesso utilizziamo SSL condivisi quando costruiamo siti di e-commerce. È un modo conveniente per ospitare più negozi senza dover acquistare certificati SSL separati per ciascun sito. La maggior parte dei nostri clienti e-commerce gestisce più negozi all'interno di una singola installazione di Magento o OpenCart. Di recente, abbiamo riscontrato un problema con Magento in cui l'ID di sessione del cliente non veniva passato correttamente tra la visita iniziale al sito e le visualizzazioni della pagina dopo aver effettuato l'accesso al negozio come cliente registrato. Magento non stava trasmettendo gli stessi ID sessione e ciò significava che un cliente che aveva precedentemente effettuato l'accesso e aggiunto articoli al carrello, avrebbe perso il contenuto del carrello dopo essere tornato in seguito e aver effettuato l'accesso. Non è una grande situazione.

Osservando i cookie creati durante una sessione, ho scoperto che quando si passava da un dominio non sicuro (ad es. Http: //) a un dominio protetto (ad es. Https: //), l'ID di sessione veniva passato correttamente e un nuovo il cookie per il dominio protetto è stato creato con lo stesso ID sessione del dominio non sicuro. Tuttavia, quando il cliente ha effettuato l'accesso, è stato creato un nuovo cookie per il dominio protetto con un ID sessione completamente nuovo. Magento ora utilizzava il cookie più recente e ogni volta che il cliente faceva clic per tornare a una pagina di dominio non protetta (ad esempio la pagina dei dettagli del prodotto), non veniva più eseguito l'accesso a Magento poiché il dominio non sicuro utilizzava il suo ID cookie / sessione, non il nuovo ID sessione creato all'accesso. La soluzione sarebbe quella di trovare dove è stato creato il nuovo ID sessione e impedire che ciò accada.

Quindi, ho iniziato a scavare nel codice per vedere se potevo trovare dove Magento stava creando la nuova sessione.

In app / code / core / Mage / Customer / Model / session.php, l'ho trovato nelle righe 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;
}

La mia soluzione era quella di commentare la riga: $ this-> renewSession () :, in modo che Magento non creasse una nuova sessione quando il cliente effettuava l'accesso. Il codice modificato è simile al seguente:

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

Finora nei nostri test, tutto funziona perfettamente e la sessione del cliente viene mantenuta tra i domini. Ora, prima di affrettarti a modificare questo file principale, procedi come segue:

Effettua il backup dei tuoi database (dovresti sempre farlo prima di apportare qualsiasi modifica). Crea la seguente gerarchia di directory: app / code / local / Mage / Customer / Model /. Metti una copia di session.php in questa nuova directory. Commenta la riga appropriata, mostrata sopra, e salva il tuo file. Inserendo le modifiche nella directory app / code / local, stai dicendo a Magento di utilizzare questi file anziché i file principali. Ancora più importante, stai impedendo la perdita delle modifiche se dovessi aggiornare Magento in futuro.

Fornisce anche un modo conveniente per archiviare e gestire le modifiche del codice, poiché è necessario conservare solo i file modificati nella directory app / code / local.

Assicurati di lasciare un commento se conosci una soluzione più elegante o se ritieni che funzioni o non funzioni per te.


4
Per modifiche archiviate in app/code/local/Mage/*. Prima dell'aggiornamento di Magento, estrai il codice dall'installer, confronta con il tuo codice modificato per vedere se è diverso. In tal caso, modificare la nuova versione da mettere in atto dopo l'aggiornamento. Niente come averlo conservato durante l'aggiornamento per far cadere il sito a causa di modifiche incompatibili nei contenuti.
Fiasco Labs,

3
Concordato. Questo articolo si applica comunque solo alle installazioni precedenti alla 1.8 poiché sono passati $this->renewSession();alla setCustomerAsLoggedIn()funzione.
seanbreeden,

1
Per le versioni più recenti di Magento, basta cercare "renewSession ()" e lo troverai in code/core/Mage/Core/Model/Session/Abstract.phpe code/core/Mage/Admin/Model/Session.phpdove può essere commentato. In una copia locale del modello, ovviamente. @FiascoLabs ancora meglio, esegue una corretta sostituzione della sola funzione che devi modificare e lascia il resto del file intatto nel core :)
WackGet

1
questo ci ha aiutato dopo 3 settimane di tentativi di risoluzione dei problemi, 4 anni dopo. Il problema si è manifestato per noi (Magento 1.9.3.2) quando abbiamo installato Amasty FPC e testato il caricamento del nostro server. ovvero impossibile accedere con Facebook e / o il normale accesso, impossibile aggiungere al carrello quando il server è sotto carico. Dopodiché, anche a vuoto il problema si è manifestato. Ora, attualmente sembra che il problema sia stato corretto dopo aver seguito la tua risposta. Grazie mille @seanbreeden. Hai dato nuova vita a sviluppatori molto stanchi. <3
ali
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.