¿Cómo cambiar el tiempo de espera de la sesión en PHP?
Me gustaría extender el tiempo de espera de la sesión en php
Sé que es posible hacerlo modificando el archivo php.ini. Pero no tengo acceso a él.
Entonces, ¿es posible hacerlo sólo con código php?
El tiempo de espera de la sesión es una noción que debe implementarse en el código si desea garantías estrictas; esa es la única manera de estar absolutamente seguro de que ninguna sesión sobrevivirá después de X minutos de inactividad.
Si relajar un poco este requisito es aceptable y está de acuerdo con colocar un límite inferior en lugar de un límite estricto para la duración, puede hacerlo fácilmente y sin escribir una lógica personalizada.
Comodidad en ambientes relajados: cómo y por qué
Si sus sesiones se implementan con cookies (que probablemente lo sean) y si los clientes no son maliciosos, puede establecer un límite superior en la duración de la sesión modificando ciertos parámetros. Si está utilizando el manejo de sesiones predeterminado de PHP con cookies, la configuración session.gc_maxlifetime
junto con session_set_cookie_params
debería funcionar de esta manera:
// server should keep session data for AT LEAST 1 hour
ini_set('session.gc_maxlifetime', 3600);
// each client should remember their session id for EXACTLY 1 hour
session_set_cookie_params(3600);
session_start(); // ready to go!
Esto funciona configurando el servidor para mantener los datos de la sesión durante al menos una hora de inactividad e indicando a sus clientes que deben "olvidar" su ID de sesión después del mismo período de tiempo. Ambos pasos son necesarios para lograr el resultado esperado.
Si no les dice a los clientes que olviden su ID de sesión después de una hora (o si los clientes son maliciosos y eligen ignorar sus instrucciones), seguirán usando la misma ID de sesión y su duración efectiva no será determinista. Esto se debe a que las sesiones cuya vida útil ha expirado en el lado del servidor no se recolectan como basura inmediatamente, sino solo cada vez que se inicia la sesión GC .
La GC es un proceso potencialmente costoso, por lo que normalmente la probabilidad es bastante pequeña o incluso nula (un sitio web que recibe una gran cantidad de visitas probablemente renunciará por completo a la GC probabilística y la programará para que se realice en segundo plano cada X minutos). En ambos casos (suponiendo que los clientes no cooperen), el límite inferior para la duración efectiva de las sesiones será
session.gc_maxlifetime
, pero el límite superior será impredecible.Si no establece
session.gc_maxlifetime
el mismo intervalo de tiempo, es posible que el servidor descarte los datos de la sesión inactiva antes de esa fecha; en este caso, un cliente que aún recuerda su ID de sesión la presentará pero el servidor no encontrará datos asociados con esa sesión, comportándose efectivamente como si la sesión acabara de comenzar.
Certeza en entornos críticos
Puede hacer que las cosas sean completamente controlables utilizando lógica personalizada para colocar también un límite superior a la inactividad de la sesión; junto con el límite inferior desde arriba, esto da como resultado una configuración estricta.
Haga esto guardando el límite superior junto con el resto de los datos de la sesión:
session_start(); // ready to go!
$now = time();
if (isset($_SESSION['discard_after']) && $now > $_SESSION['discard_after']) {
// this session has worn out its welcome; kill it and start a brand new one
session_unset();
session_destroy();
session_start();
}
// either new or old, it should live at most for another hour
$_SESSION['discard_after'] = $now + 3600;
Persistencia de identificación de sesión
Hasta ahora no nos hemos preocupado en absoluto por los valores exactos de cada ID de sesión, solo por el requisito de que los datos existan durante el tiempo que los necesitemos. Tenga en cuenta que en el (improbable) caso de que los ID de sesión le importen, debe tener cuidado de regenerarlos session_regenerate_id
cuando sea necesario.
Si utiliza el manejo de sesiones predeterminado de PHP, la única forma de cambiar de manera confiable la duración de la sesión en todas las plataformas es cambiar php.ini . Esto se debe a que en algunas plataformas, la recolección de basura se implementa a través de un script que se ejecuta cada cierto tiempo (un script cron ) que lee directamente desde php.ini y, por lo tanto, cualquier intento de cambiarlo en tiempo de ejecución, por ejemplo, a través de ini_set()
, no es confiable y muy probablemente no funcionará.
Por ejemplo, en los sistemas Debian Linux, la recolección de basura interna de PHP está deshabilitada de manera session.gc_probability=0
predeterminada en la configuración, y en su lugar se realiza a través de /etc/cron.d/php, que se ejecuta en XX:09 y XX:39 (es decir, Cada media hora). Este trabajo cron busca sesiones anteriores al session.gc_maxlifetime especificado en la configuración y, si se encuentra alguna, se elimina. Como consecuencia, en estos sistemas ini_set('session.gc_maxlifetime', ...)
se ignora. Eso también explica por qué en esta pregunta: las sesiones de PHP se agotan demasiado rápido , el OP tuvo problemas en un host pero los problemas cesaron al cambiar a un host diferente.
Entonces, dado que no tiene acceso a php.ini , si desea hacerlo de forma portátil, usar el manejo de sesión predeterminado no es una opción. Aparentemente, extender la vida útil de las cookies fue suficiente para su host, pero si desea una solución que funcione de manera confiable incluso si cambia de host, debe usar una alternativa diferente.
Los métodos alternativos disponibles incluyen:
Configure un controlador de sesión (guardado) diferente en PHP para guardar sus sesiones en un directorio diferente o en una base de datos, como se especifica en PHP: Controladores de sesión personalizados (manual de PHP) , para que el trabajo cron no llegue a él, y solo PHP Se realiza la recolección interna de basura. Esta opción probablemente pueda usarse
ini_set()
para configurar session.gc_maxlifetime , pero prefiero simplemente ignorar el parámetro maxlifetime en migc()
devolución de llamada y determinar la vida útil máxima por mi cuenta.Olvídese por completo del manejo de sesiones internas de PHP e implemente su propia gestión de sesiones. Este método tiene dos desventajas principales: necesitará sus propias variables de sesión globales, por lo que perderá la ventaja del
$_SESSION
superglobal, y necesita más código, por lo que hay más oportunidades de errores y fallas de seguridad. Lo más importante es que el identificador de sesión debe generarse a partir de números aleatorios o pseudoaleatorios criptográficamente seguros para evitar la previsibilidad del ID de sesión (lo que lleva a un posible secuestro de sesión), y eso no es tan fácil de hacer con PHP de forma portátil. La principal ventaja es que funcionará de manera consistente en todas las plataformas y usted tendrá control total sobre el código. Ese es el enfoque adoptado, por ejemplo, por el software del foro phpBB (al menos la versión 1; no estoy seguro acerca de las versiones más recientes).
Hay un ejemplo de (1) en la documentación desession_set_save_handler()
. El ejemplo es largo pero lo reproduciré aquí, con las modificaciones pertinentes necesarias para ampliar la duración de la sesión. session_set_cookie_params()
Tenga en cuenta también la inclusión de para aumentar la vida útil de las cookies.
<?php
class FileSessionHandler
{
private $savePath;
private $lifetime;
function open($savePath, $sessionName)
{
$this->savePath = 'my_savepath'; // Ignore savepath and use our own to keep it safe from automatic GC
$this->lifetime = 3600; // 1 hour minimum session duration
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
}
return true;
}
function close()
{
return true;
}
function read($id)
{
return (string)@file_get_contents("$this->savePath/sess_$id");
}
function write($id, $data)
{
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
}
function destroy($id)
{
$file = "$this->savePath/sess_$id";
if (file_exists($file)) {
unlink($file);
}
return true;
}
function gc($maxlifetime)
{
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $this->lifetime < time() && file_exists($file)) { // Use our own lifetime
unlink($file);
}
}
return true;
}
}
$handler = new FileSessionHandler();
session_set_save_handler(
array($handler, 'open'),
array($handler, 'close'),
array($handler, 'read'),
array($handler, 'write'),
array($handler, 'destroy'),
array($handler, 'gc')
);
// the following prevents unexpected effects when using objects as save handlers
register_shutdown_function('session_write_close');
session_set_cookie_params(3600); // Set session cookie duration to 1 hour
session_start();
// proceed to set and retrieve values by key from $_SESSION
El enfoque (2) es más complicado; Básicamente, debes volver a implementar todas las funciones de la sesión por tu cuenta. No entraré en detalles aquí.