Problema de inicio de sesión errático relacionado con cookies


8

esta será larga ...

Tengo un caso grave de error de inicio de sesión errático, debido a la gestión incorrecta de cookies. En primer lugar, estoy administrando una tienda cerrada (B2B) en la que los clientes deben iniciar sesión antes de que puedan ver el catálogo. Cada acceso no registrado se redirige a la página de inicio de sesión, pero de vez en cuando el cliente no puede iniciar sesión incluso si el nombre de usuario y la contraseña son correctos. Digo 'nombre de usuario' porque uso la extensión Diglin_Username y el complemento StoreRestricition para lograr el comportamiento deseado. Lo que sucede es que a veces encontré dos conjuntos diferentes de cookies dejados por Magento, y se refieren a dos dominios diferentes (.www.abc.com y .abc.com, por ejemplo).

Después de leer este artículo del gran Alan Storm sobre la creación de instancias en las primeras sesiones, y encontrar la temida cookie PHPSESSID en mi navegador, investigué con cierta profundidad el problema.

Lo que encontré es de dos caras. Primero puse una llamada Mage :: Log () en la función start () en la clase Mage_Core_Model_Session_Abstract_Varien para registrar los diversos intentos realizados por Magento para iniciar una nueva sesión y noté que después de la primera invocación de Mage :: run (), preDispatch () , los métodos dispatch () y postDispatch () de la clase Mage_Core_Controller_Front_Action se invocan en la secuencia habitual, pero parece que cuando se ejecuta postDispatch () no puede encontrar la sesión iniciada por preDispatch () y procede a crear una nueva sesión. A este respecto, encontré una diferencia en el código entre la versión 1.7.xy 1.8.x de Magento y creo que tal vez podría solucionar el problema:

Magento 1.7.x - Clase Mage_Core_Model_Session_Abstract_Varien:

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

Magento 1.8.x - Clase Mage_Core_Model_Session_Abstract_Varien:

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

Sin embargo, no puedo encontrar dónde establecer la propiedad SkipEmptySessionCheck, así que terminé parcheando la clase Mage_Core_Controller_Front_Action de esta manera:

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

tener postDispatch () sin llamar a Mage :: getSingleton ('core / session') (que habría creado una nueva sesión) si no puede encontrar una sesión ya iniciada. Adiós a la cookie PHPSESSID y todo listo, pensé ...

Pero no es asi. Ahora me deshice de la cookie PHPSESSID pero aún tengo que pasar a dos conjuntos diferentes de cookies (erráticamente) guardados en el navegador. Solo borrando las cookies incorrectas puedo iniciar sesión con éxito, o me redirigen a la página de inicio de sesión sin siquiera un mensaje. Traté de establecer el dominio de cookies explícitamente en la configuración del sistema, pero esto no resolvió el problema.

Profundamente en la base de código nuevamente, y descubrí que en los diversos lugares cuando Magento establece una cookie, toma el dominio para usar desde la función getDomain () en la clase Mage_Core_Model_Cookie:

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

Ahora, si mira la página que obtiene de Magento en su navegador, puede encontrar en la sección 'cabeza' algo como esto:

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

Estas líneas provienen de 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>

y a su vez este código hace referencia a la función getDomain () en la clase Mage_Page_Block_Js_Cookie:

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

Entonces, si configuro el dominio de cookies en la configuración del sistema como, por ejemplo, 'www.abc.com' termino con:

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

y al encontrar en mi navegador las cookies 'www.abc.com' y '.www.abc.com' pensé, "ok, estableceré '.abc.com' en la configuración del sistema y siempre terminaré con ' .abc.com 'cookies !! "...

Pero de ninguna manera. Ahora en mi página HTML siempre obtengo '.abc.com' pero aun así recibí una cookie 'www.abc.com' y no inicié sesión.

Estoy perplejo, y mi cliente está empezando a pensar que no soy tan bueno como él pensaba que era (también estoy empezando a pensar que ...) :(

¿Algunos de ustedes (y chicas) tienen alguna pista?

ACTUALIZACIÓN: He visto a alguien relacionando problemas con las sesiones y las cookies con el uso de Varnish como caché para Magento. Como también estoy usando Varnish, intentaré si deshabilitarlo el problema se puede resolver.


Hola Marius, ¿por qué la edición? ¿Estoy rompiendo alguna regla del foro?
slamarca

Estamos viendo el mismo comportamiento (inicio de sesión y el cliente pierde sesión), ¡excepto que no podemos reproducir el problema de ninguna manera! Esto realmente complica cualquier intento de solución de problemas, y mucho menos resolver el problema. ¿Cómo replicaste el problema de manera confiable? @Sander Mangel: esa es la cuestión, no he podido reproducir el problema, así que no puedo estar seguro de cómo son las diferentes cookies. Sería mucho más feliz si pudiera reproducirlo para poder verificar cualquier solución hecha para resolver el problema. Esperaba que alguno de ustedes pudiera señalarme en la dirección correcta sobre cómo reproducir el problema. ¡Gracias!

@ Zhulak mismo problema con www. y no www. ¿galletas?
Sander Mangel

Respuestas:


8

Este es un artículo de NovusWeb: http://www.novusweb.com/fix-for-passing-magento-session-ids/

Solución para pasar ID de sesión de Magento

Autor: Brett Williams

Publicado el 9 de noviembre de 2011

Arreglando ID de sesión de Magento

A menudo usamos SSL compartidos cuando construimos sitios de comercio electrónico. Es una forma conveniente de alojar múltiples tiendas sin tener que comprar certificados SSL por separado para cada sitio. La mayoría de nuestros clientes de comercio electrónico administran múltiples tiendas dentro de una sola instalación de Magento u OpenCart. Recientemente, encontramos un problema con Magento en el que el ID de sesión del cliente no se pasaba con éxito entre su visita inicial al sitio y sus visitas a la página después de iniciar sesión en la tienda como cliente registrado. Magento no estaba pasando las mismas ID de sesión, y esto significaba que un cliente que había iniciado sesión previamente y había agregado artículos a su carrito, perdería el contenido de su carrito después de regresar más tarde e iniciar sesión. No es una gran situación.

Al observar las cookies creadas durante una sesión, descubrí que al pasar de un dominio no seguro (es decir, http: //) a un dominio seguro (es decir, https: //), la ID de la sesión se pasaba con éxito y se generaba un nuevo la cookie para el dominio seguro se creó con la misma ID de sesión que el dominio no seguro. Sin embargo, cuando el cliente inició sesión, se creó una nueva cookie para el dominio seguro con una ID de sesión completamente nueva. Magento ahora estaba usando la cookie más nueva, y cada vez que el cliente hacía clic para volver a una página de dominio no segura (por ejemplo, página de detalles del producto), ya no iniciaba sesión en Magento ya que el dominio no seguro estaba usando su cookie / ID de sesión, no la nueva ID de sesión creado al iniciar sesión. La solución sería encontrar dónde se creó la nueva ID de sesión y evitar que eso ocurra.

Entonces, comencé a investigar el código para ver si podía encontrar dónde estaba creando Magento la nueva sesión.

En app / code / core / Mage / Customer / Model / session.php, encontré esto en las líneas 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;
}

Mi solución fue comentar la línea: $ this-> renewSession () :, para que Magento no creara una nueva sesión cuando el cliente iniciara sesión. El código modificado se ve así:

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

Hasta ahora, en nuestras pruebas, todo funciona bien y la sesión del cliente se retiene entre dominios. Ahora, antes de apresurarse a cambiar este archivo principal, haga lo siguiente:

Haga una copia de seguridad de sus bases de datos (siempre debe hacer esto antes de realizar cualquier modificación). Cree la siguiente jerarquía de directorios: app / code / local / Mage / Customer / Model /. Ponga una copia de session.php en este nuevo directorio. Comente la línea apropiada, que se muestra arriba, y guarde su archivo. Al poner sus modificaciones en el directorio de la aplicación / código / local, le está diciendo a Magento que use estos archivos en lugar de los archivos principales. Más importante aún, está evitando la pérdida de sus modificaciones si actualiza Magento en el futuro.

También proporciona una manera conveniente de almacenar y administrar las modificaciones de su código, ya que solo necesita mantener los archivos modificados en el directorio de la aplicación / código / local.

Asegúrese de dejar un comentario si conoce una solución más elegante, o si encuentra que esto funciona o no funciona para usted.


44
Para modificaciones almacenadas en app/code/local/Mage/*. Antes de la actualización de Magento, extraiga el código del instalador, compárelo con su código modificado para ver si es diferente. Si es así, modifique la nueva versión que se implementará después de la actualización. Nada como conservarlo en la actualización para que el sitio se caiga debido a cambios incompatibles en los contenidos.
Fiasco Labs

3
Convenido. Este artículo solo se aplicaría a las instalaciones previas a 1.8 de todos modos ya que se trasladaron $this->renewSession();a la setCustomerAsLoggedIn()función
seanbreeden

1
Para versiones más actuales de Magento, solo busque "renewSession ()" y lo encontrará en code/core/Mage/Core/Model/Session/Abstract.phpy code/core/Mage/Admin/Model/Session.phpdonde puede comentarse. En una copia local del modelo, por supuesto. @FiascoLabs aún mejor, realice una anulación adecuada de solo la función que necesita modificar y deje el resto del archivo intacto en el núcleo :)
WackGet

1
Esto nos ha ayudado después de 3 semanas de intentar solucionar el problema, 4 años después. El problema se nos manifestó (Magento 1.9.3.2) cuando instalamos Amasty FPC y probamos nuestro servidor. es decir, no puede iniciar sesión con Facebook y / o inicio de sesión normal, no puede agregar al carrito cuando el servidor está bajo carga. Después de lo cual, incluso sin carga, el problema se manifestó. Ahora, actualmente parece que el problema se solucionó después de seguir su respuesta. Muchas gracias @seanbreeden. Has dado nueva vida a desarrolladores muy cansados. <3
Ali
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.