Cómo evitar la expiración de las sesiones en PHP

En un proyecto que hice para un cliente me sucedió algo que no había previsto: un formulario dinámico resultó muy largo para la persona que tenía que realizar la carga y, cuando terminó el sistema la deslogueó automáticamente y perdió su trabajo 🙁

Analizando un poco el problema me di cuenta de que la sesión había expirado a pesar de que el usuario estaba interactuando con el sistema… sólo que no se estaba produciendo ninguna comunicación cliente-servidor, ya que toda la acción estaba pasando del lado cliente.

A juzgar por algunos comentarios que he leído por ahí, como:

Tengo un archivo sesion.php que se incluye en cada pagina del proyecto, para validar tanto si la sesión esta activa, como si la sesión ha expirado, estoy haciendo pruebas con 30 segundos para no tardar tanto.

El problema surge que el código se ejecuta cada vez que visito una pagina, por lo tanto si estoy navegando sobre la misma pagina, como por ejemplo haciendo click o registrando datos, la sesión aún así expira.

O también:

Tengo mi web en un servidor de GoDaddy y manejo sesiones pero estas caducan solas por inactividad..

Parece que no estoy solo en este sufrimiento 🙂

La solución que encontré fue diseñar un mecanismo de tipo keepAlive de modo de avisar al servidor que todavía había actividad del lado del cliente (¡y pedir por favor que no me dejen afuera!).

Lo primero que hice entonces fue agregar este pequeño código javascript:

<script type="text/javascript">
    var keep_alive = false;

    $(document).bind("click keydown keyup mousemove", function() {
        keep_alive = true;
    });

    setInterval(function() {
        if ( keep_alive ) {
            pingServer();
            keep_alive = false;
        }
    }, 1200000 );

    function pingServer() {
        $.ajax('/keepAlive');
    }
</script>

La idea es llevar un control sobre cualquier evento que se suceda del lado cliente (Click, presionar una tecla o mover el mouse) y, cada tanto (20 minutos en mi caso), si hubo actividad, avisarle al server para prolongar la vida de la sesión.

Cómo extender dinámicamente la vida de una sesión

Del lado del servidor no hay mucho que hacer en realidad, basta con tener algún script que responda a la URI /keepAlive (Preferentemente con un 200 OK) y listo.

Hay algunas otras cosas a tener en cuenta si, como en mi caso, la aplicación está corriendo en un ambiente de hosting compartido (Algo que trato de evitar por todos los medios, pero bueno… en este caso no pude):

  1. Dónde se almacena la información de las sesiones propias de la aplicación
  2. Cuál es el tiempo de vida de la sesión
  3. Cada cuánto tiempo se libera la basura de las sesiones

La respuesta a estas tres preguntas (y otras más) está en el viejo y querido php.ini. Específicamente en las claves:

Como cualquier otro setting de php, puede modificarse desde el propio código de nuestra aplicación (¡Pero hay que acordarse de hacerlo!).

Un detalle interesante es esta notita sobre session.gc_maxlifetime:

Nota: Si diferentes scripts tienen diferentes valores de session.gc_maxlifetime pero comparten la misma ubicación para almacenar la información de sesión, la información del script con el mínimo valor será limpiada. En este caso use esta directiva junto con session.save_path.

No puedo estar seguro al 100%, pero mi apuesta más fuerte es que este fue el problema: mi aplicación estaba guardando sus archivos de sesión en el mismo lugar que otra y, cuando pasó el garbage collector… ¡adiós!

¿Tuviste alguna vez problemas de este tipo con tus aplicaciones web?

mchojrin

Por mchojrin

Ayudo a desarrolladores PHP a acceder mercados y clientes más sofisticados y exigentes

3 comentarios

¿Te quedó alguna duda? Publica aca tu pregunta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.