Tenga en cuenta que al menos dos configuraciones son cruciales para configurar el tiempo de sesión, y tal vez tres. Los dos ciertamente cruciales son session.gc_maxlifetime y session.cookie_lifetime (donde 0 no es lo mismo que un número largo). Para completar, 100% de certeza de permitir largos tiempos, también puede ser necesario configurar el session.save_path, debido al tiempo de limpieza variable controlado por el sistema operativo en el directorio / tmp donde los archivos de sesión se almacenan por defecto.
Kzqai
1
No entiendo por qué quieres caducar la sesión. Si le preocupa que el usuario abandone su computadora sin cerrar sesión, y un usuario no autorizado se haga cargo de su computadora, el vencimiento de la sesión en su sitio no impedirá que el secuestrador acceda a los archivos de la víctima en el disco.
Gqqnbig
No está claro lo que estás preguntando aquí. ¿Quiere decir que desea implementar un tiempo de espera de inactividad difícil (actualmente PHP felizmente le permitirá usar una sesión que no ha sido tocada por más de session.gc_maxlifetime) o quiere decir que desea limitar la sesión a 30 minutos independientemente de ¿inactividad? Francamente, creo que la respuesta aceptada aquí es un mal consejo para cualquier problema: en ambos casos, la lógica debe implementarse con un controlador de sesión personalizado.
symcbean
Respuestas:
1663
Debe implementar un tiempo de espera de sesión propio. Ambas opciones mencionadas por otros ( session.gc_maxlifetime y session.cookie_lifetime ) no son confiables. Explicaré las razones de eso.
Primero:
session.gc_maxlifetime session.gc_maxlifetime especifica el número de segundos después de los cuales los datos serán vistos como 'basura' y limpiados. La recolección de basura ocurre durante el inicio de la sesión.
Pero el recolector de basura solo se inicia con una probabilidad de session.gc_probability dividida por session.gc_divisor . Y utilizando los valores predeterminados para esas opciones (1 y 100 respectivamente), la probabilidad es solo del 1%.
Bueno, simplemente puede ajustar estos valores para que el recolector de basura se inicie con más frecuencia. Pero cuando se inicia el recolector de basura, verificará la validez de cada sesión registrada. Y eso es costoso.
Además, cuando se usan los archivos session.save_handler predeterminados de PHP , los datos de la sesión se almacenan en archivos en una ruta especificada en session.save_path . Con ese controlador de sesión, la antigüedad de los datos de la sesión se calcula en la última fecha de modificación del archivo y no en la última fecha de acceso:
Nota: Si está utilizando el controlador de sesión predeterminado basado en archivos, su sistema de archivos debe realizar un seguimiento de los tiempos de acceso (atime). Windows FAT no lo hace, por lo que tendrá que encontrar otra forma de manejar la recolección de basura de su sesión si está atascado con un sistema de archivos FAT o cualquier otro sistema de archivos donde el seguimiento de tiempo no esté disponible. Desde PHP 4.2.3 ha usado mtime (fecha de modificación) en lugar de atime. Por lo tanto, no tendrá problemas con los sistemas de archivos donde el seguimiento de atime no está disponible.
Por lo tanto, también puede ocurrir que un archivo de datos de sesión se elimine mientras la sesión en sí misma todavía se considera válida porque los datos de la sesión no se actualizaron recientemente.
Y segundo:
session.cookie_lifetime session.cookie_lifetime especifica la duración de la cookie en segundos que se envía al navegador. [...]
Si, eso es correcto. Esto solo afecta la vida útil de la cookie y la sesión misma puede ser válida. Pero es tarea del servidor invalidar una sesión, no el cliente. Entonces esto no ayuda en nada. De hecho, tener session.cookie_lifetime configurado en 0haría que la cookie de la sesión sea una cookie de sesión real que solo es válida hasta que se cierre el navegador.
Conclusión / mejor solución:
La mejor solución es implementar un tiempo de espera de sesión propio. Use una marca de tiempo simple que indique la hora de la última actividad (es decir, la solicitud) y actualícela con cada solicitud:
if(isset($_SESSION['LAST_ACTIVITY'])&&(time()- $_SESSION['LAST_ACTIVITY']>1800)){// last request was more than 30 minutes ago
session_unset();// unset $_SESSION variable for the run-time
session_destroy();// destroy session data in storage}
$_SESSION['LAST_ACTIVITY']= time();// update last activity time stamp
La actualización de los datos de sesión con cada solicitud también cambia la fecha de modificación del archivo de sesión para que el recolector de basura no elimine la sesión prematuramente.
También puede usar una marca de tiempo adicional para regenerar la ID de la sesión periódicamente para evitar ataques en sesiones como la fijación de la sesión :
if(!isset($_SESSION['CREATED'])){
$_SESSION['CREATED']= time();}elseif(time()- $_SESSION['CREATED']>1800){// session started more than 30 minutes ago
session_regenerate_id(true);// change session ID for the current session and invalidate old session ID
$_SESSION['CREATED']= time();// update creation time}
Notas:
session.gc_maxlifetime debe ser al menos igual a la vida útil de este controlador de caducidad personalizado (1800 en este ejemplo);
si desea expirar la sesión después de 30 minutos de actividad en lugar de transcurridos 30 minutos desde el inicio , también deberá usar setcookieuna expiración de time()+60*30para mantener activa la cookie de sesión.
¿Cómo podría alterar esto si quisiera verificar el "tiempo inactivo"? En otras palabras, el usuario inicia sesión y, mientras continúe usando el sitio, no cerrará sesión. Sin embargo, si están inactivos durante 30 minutos, ¿los cerrará sesión?
Metropolis
14
@Metropolis: use algo $_SESSION['LAST_ACTIVITY']similar a $_SESSION['CREATED']donde almacena el tiempo de la última actividad del usuario, pero actualice ese valor con cada solicitud. Ahora, si la diferencia de ese tiempo con el tiempo actual es mayor que 1800 segundos, la sesión no se ha utilizado durante más de 30 minutos.
Gumbo
3
@Metropolis: session_unsethace lo mismo que $_SESSION = array().
Gumbo
14
@Gumbo - Estoy un poco confundido, ¿no deberías usar tu código en combinación con ini_set('session.gc-maxlifetime', 1800)? De lo contrario, la información de su sesión podría destruirse mientras se supone que su sesión todavía es válida, al menos si la configuración inicial es el estándar de 24 minutos. ¿O me estoy perdiendo algo?
jeroen 27/10/10
10
@jeron: Sí, deberías. Pero tenga en cuenta que session.gc_maxlifetime depende de la última fecha de modificación del archivo si filesse utiliza el controlador de guardado de sesión . Por lo tanto, session.gc_maxlifetime debería ser al menos igual al tiempo de vida de este controlador de caducidad personalizado.
Gumbo
135
Forma simple de expiración de sesión PHP en 30 minutos.
Nota: si desea cambiar la hora, simplemente cambie el 30 con el tiempo deseado y no cambie * 60: esto le dará los minutos.
En minutos: (30 * 60)
En días: (n * 24 * 60 * 60) n = no de días
Login.php
<?php
session_start();?><html><formname="form1"method="post"><table><tr><td>Username</td><td><inputtype="text"name="text"></td></tr><tr><td>Password</td><td><inputtype="password"name="pwd"></td></tr><tr><td><inputtype="submit"value="SignIn"name="submit"></td></tr></table></form></html><?php
if(isset($_POST['submit'])){
$v1 ="FirstUser";
$v2 ="MyPassword";
$v3 = $_POST['text'];
$v4 = $_POST['pwd'];if($v1 == $v3 && $v2 == $v4){
$_SESSION['luser']= $v1;
$_SESSION['start']= time();// Taking now logged in time.// Ending a session in 30 minutes from the starting time.
$_SESSION['expire']= $_SESSION['start']+(30*60);
header('Location: http://localhost/somefolder/homepage.php');}else{
echo "Please enter the username or password again!";}}?>
HomePage.php
<?php
session_start();if(!isset($_SESSION['luser'])){
echo "Please Login again";
echo "<a href='http://localhost/somefolder/login.php'>Click Here to Login</a>";}else{
$now = time();// Checking the time now when home page starts.if($now > $_SESSION['expire']){
session_destroy();
echo "Your session has expired! <a href='http://localhost/somefolder/login.php'>Login here</a>";}else{//Starting this else one [else1]?><!-- From here all HTML coding can be done --><html>
Welcome
<?php
echo $_SESSION['luser'];
echo "<a href='http://localhost/somefolder/logout.php'>Log out</a>";?></html><?php
}}?>
La combinación de lógica y presentación no es aconsejable en estos días cuando MVC es la norma.
bcosca
Tal vez me estoy perdiendo algo elemental sobre las sesiones, pero ¿de qué sirve esto si las sesiones son destruidas cada 30 minutos por el sistema operativo?
25
@stillstanding Habla por ti mismo [sonrisa] Veo MVC como una abominación.
2
¿MVC es una buena idea incluso cuando el proyecto es pequeño, con un solo programador? Siento que debería hacer mis propios proyectos en el modelo MVC (o resolver el problema ENTONCES hacerlo MVC) pero con la falta de experiencia con MVC se convierte en un bloqueo mental "¿Cómo hago este MVC?" y una distracción del objetivo / problema inicial que requiere una solución.
MrVimes
@todavía otra mención es que en los Login.phpencabezados se envían DESPUÉS del contenido, lo cual es malo.
machineaddict
43
¿Esto es para desconectar al usuario después de un tiempo establecido? Establecer el tiempo de creación de la sesión (o un tiempo de caducidad) cuando está registrado, y luego verificar eso en cada carga de página podría manejar eso.
session.gc-maxlifetime es probablemente la mejor manera de hacerlo.
Powerlord
2
Hay algunos problemas con la duración de la cookie de sesión, sobre todo, depende del cliente para hacerla cumplir. La vida útil de las cookies está ahí para permitir al cliente limpiar las cookies inútiles / caducadas, no debe confundirse con nada relacionado con la seguridad.
Jacco
Es gc_maxlifetimeo gc-maxlifetime. ¿Es compatible con guiones bajos y guiones?
En mi humilde opinión, la segunda opción es una buena solución:
<?php
/***
* Starts a session with a specific timeout and a specific GC probability.
* @param int $timeout The number of seconds until it should time out.
* @param int $probability The probablity, in int percentage, that the garbage
* collection routine will be triggered right now.
* @param strint $cookie_domain The domain path for the cookie.
*/function session_start_timeout($timeout=5, $probability=100, $cookie_domain='/'){// Set the max lifetime
ini_set("session.gc_maxlifetime", $timeout);// Set the session cookie to timout
ini_set("session.cookie_lifetime", $timeout);// Change the save path. Sessions stored in teh same path// all share the same lifetime; the lowest lifetime will be// used for all. Therefore, for this to work, the session// must be stored in a directory where only sessions sharing// it's lifetime are. Best to just dynamically create on.
$seperator = strstr(strtoupper(substr(PHP_OS,0,3)),"WIN")?"\\":"/";
$path = ini_get("session.save_path"). $seperator ."session_". $timeout ."sec";if(!file_exists($path)){if(!mkdir($path,600)){
trigger_error("Failed to create session save path directory '$path'. Check permissions.", E_USER_ERROR);}}
ini_set("session.save_path", $path);// Set the chance to trigger the garbage collection.
ini_set("session.gc_probability", $probability);
ini_set("session.gc_divisor",100);// Should always be 100// Start the session!
session_start();// Renew the time left until this session times out.// If you skip this, the session will time out based// on the time when it was created, rather than when// it was last used.if(isset($_COOKIE[session_name()])){
setcookie(session_name(), $_COOKIE[session_name()], time()+ $timeout, $cookie_domain);}}
Bueno, entiendo que las respuestas anteriores son correctas, pero están en el nivel de aplicación, ¿por qué no usamos simplemente el .htaccessarchivo para establecer el tiempo de caducidad?
En realidad es fácil con una función como la siguiente. Utiliza el nombre de la tabla de la base de datos 'sesiones' con los campos 'id' y 'hora'.
Cada vez que el usuario visite su sitio o servicio nuevamente, debe invocar esta función para verificar si su valor de retorno es VERDADERO. Si es FALSO, el usuario ha expirado y la sesión se destruirá (Nota: esta función utiliza una clase de base de datos para conectarse y consultar la base de datos, por supuesto, también puede hacerlo dentro de su función o algo así):
function session_timeout_ok(){global $db;
$timeout = SESSION_TIMEOUT;//const, e.g. 6 * 60 for 6 minutes
$ok =false;
$session_id = session_id();
$sql ="SELECT time FROM sessions WHERE session_id = '".$session_id."'";
$rows = $db->query($sql);if($rows ===false){//Timestamp could not be read
$ok = FALSE;}else{//Timestamp was read succesfullyif(count($rows)>0){
$zeile = $rows[0];
$time_past = $zeile['time'];if( $timeout + $time_past < time()){//Time has expired
session_destroy();
$sql ="DELETE FROM sessions WHERE session_id = '". $session_id ."'";
$affected = $db -> query($sql);
$ok = FALSE;}else{//Time is okay
$ok = TRUE;
$sql ="UPDATE sessions SET time='". time()."' WHERE session_id = '". $session_id ."'";
$erg = $db -> query($sql);if($erg ==false){//DB error}}}else{//Session is new, write it to database table sessions
$sql ="INSERT INTO sessions(session_id,time) VALUES ('".$session_id."','".time()."')";
$res = $db->query($sql);if($res === FALSE){//Database error
$ok =false;}
$ok =true;}return $ok;}return $ok;}
<?php
$user = $_POST['user_name'];
$pass = $_POST['user_pass'];require('db_connection.php');// Hey, always escape input if necessary!
$result = mysql_query(sprintf("SELECT * FROM accounts WHERE user_Name='%s' AND user_Pass='%s'", mysql_real_escape_string($user), mysql_real_escape_string($pass));if( mysql_num_rows( $result )>0){
$array = mysql_fetch_assoc($result);
session_start();
$_SESSION['user_id']= $user;
$_SESSION['login_time']= time();
header("Location:loggedin.php");}else{
header("Location:login.php");}?>
Ahora, compruebe si la marca de tiempo está dentro del intervalo de tiempo permitido (1800 segundos son 30 minutos)
<?php
session_start();if(!isset( $_SESSION['user_id'])|| time()- $_SESSION['login_time']>1800){
header("Location:login.php");}else{// uncomment the next line to refresh the session, so it will expire after thirteen minutes of inactivity, and not thirteen minutes after login//$_SESSION['login_time'] = time();
echo ("this session is ". $_SESSION['user_id']);//show rest of the page and all other content}?>
Puede usar directamente una base de datos para hacerlo como alternativa. Utilizo una función DB para hacerlo que llamo chk_lgn.
Verifique las verificaciones de inicio de sesión para ver si han iniciado sesión o no y, al hacerlo, establece la marca de fecha y hora de la verificación como la última activa en la fila / columna db del usuario.
También hago la verificación de tiempo allí. Esto funciona para mí por el momento, ya que uso esta función para cada página.
PD: Nadie que haya visto había sugerido una solución de DB pura.
Respuestas:
Debe implementar un tiempo de espera de sesión propio. Ambas opciones mencionadas por otros ( session.gc_maxlifetime y session.cookie_lifetime ) no son confiables. Explicaré las razones de eso.
Primero:
Pero el recolector de basura solo se inicia con una probabilidad de session.gc_probability dividida por session.gc_divisor . Y utilizando los valores predeterminados para esas opciones (1 y 100 respectivamente), la probabilidad es solo del 1%.
Bueno, simplemente puede ajustar estos valores para que el recolector de basura se inicie con más frecuencia. Pero cuando se inicia el recolector de basura, verificará la validez de cada sesión registrada. Y eso es costoso.
Además, cuando se usan los archivos session.save_handler predeterminados de PHP , los datos de la sesión se almacenan en archivos en una ruta especificada en session.save_path . Con ese controlador de sesión, la antigüedad de los datos de la sesión se calcula en la última fecha de modificación del archivo y no en la última fecha de acceso:
Por lo tanto, también puede ocurrir que un archivo de datos de sesión se elimine mientras la sesión en sí misma todavía se considera válida porque los datos de la sesión no se actualizaron recientemente.
Y segundo:
Si, eso es correcto. Esto solo afecta la vida útil de la cookie y la sesión misma puede ser válida. Pero es tarea del servidor invalidar una sesión, no el cliente. Entonces esto no ayuda en nada. De hecho, tener session.cookie_lifetime configurado en
0
haría que la cookie de la sesión sea una cookie de sesión real que solo es válida hasta que se cierre el navegador.Conclusión / mejor solución:
La mejor solución es implementar un tiempo de espera de sesión propio. Use una marca de tiempo simple que indique la hora de la última actividad (es decir, la solicitud) y actualícela con cada solicitud:
La actualización de los datos de sesión con cada solicitud también cambia la fecha de modificación del archivo de sesión para que el recolector de basura no elimine la sesión prematuramente.
También puede usar una marca de tiempo adicional para regenerar la ID de la sesión periódicamente para evitar ataques en sesiones como la fijación de la sesión :
Notas:
session.gc_maxlifetime
debe ser al menos igual a la vida útil de este controlador de caducidad personalizado (1800 en este ejemplo);setcookie
una expiración detime()+60*30
para mantener activa la cookie de sesión.fuente
$_SESSION['LAST_ACTIVITY']
similar a$_SESSION['CREATED']
donde almacena el tiempo de la última actividad del usuario, pero actualice ese valor con cada solicitud. Ahora, si la diferencia de ese tiempo con el tiempo actual es mayor que 1800 segundos, la sesión no se ha utilizado durante más de 30 minutos.session_unset
hace lo mismo que$_SESSION = array()
.ini_set('session.gc-maxlifetime', 1800)
? De lo contrario, la información de su sesión podría destruirse mientras se supone que su sesión todavía es válida, al menos si la configuración inicial es el estándar de 24 minutos. ¿O me estoy perdiendo algo?files
se utiliza el controlador de guardado de sesión . Por lo tanto, session.gc_maxlifetime debería ser al menos igual al tiempo de vida de este controlador de caducidad personalizado.Forma simple de expiración de sesión PHP en 30 minutos.
Nota: si desea cambiar la hora, simplemente cambie el 30 con el tiempo deseado y no cambie * 60: esto le dará los minutos.
En minutos: (30 * 60)
En días: (n * 24 * 60 * 60) n = no de días
Login.php
HomePage.php
LogOut.php
fuente
Login.php
encabezados se envían DESPUÉS del contenido, lo cual es malo.¿Esto es para desconectar al usuario después de un tiempo establecido? Establecer el tiempo de creación de la sesión (o un tiempo de caducidad) cuando está registrado, y luego verificar eso en cada carga de página podría manejar eso.
P.ej:
Editar: Tengo la sensación de que quieres decir algo más.
Puede eliminar sesiones después de una determinada vida útil utilizando la
session.gc_maxlifetime
configuración ini:Editar: ini_set ('session.gc_maxlifetime', 60 * 30);
fuente
gc_maxlifetime
ogc-maxlifetime
. ¿Es compatible con guiones bajos y guiones?Esta publicación muestra un par de formas de controlar el tiempo de espera de la sesión: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions
En mi humilde opinión, la segunda opción es una buena solución:
fuente
Bueno, entiendo que las respuestas anteriores son correctas, pero están en el nivel de aplicación, ¿por qué no usamos simplemente el
.htaccess
archivo para establecer el tiempo de caducidad?fuente
fuente
Utilizar el
session_set_cookie_params
función para hacer esto.Es necesario llamar a esta función antes
session_start()
llamar.Prueba esto:
Ver más en: http://php.net/manual/function.session-set-cookie-params.php
fuente
En realidad es fácil con una función como la siguiente. Utiliza el nombre de la tabla de la base de datos 'sesiones' con los campos 'id' y 'hora'.
Cada vez que el usuario visite su sitio o servicio nuevamente, debe invocar esta función para verificar si su valor de retorno es VERDADERO. Si es FALSO, el usuario ha expirado y la sesión se destruirá (Nota: esta función utiliza una clase de base de datos para conectarse y consultar la base de datos, por supuesto, también puede hacerlo dentro de su función o algo así):
fuente
Almacenar una marca de tiempo en la sesión
Ahora, compruebe si la marca de tiempo está dentro del intervalo de tiempo permitido (1800 segundos son 30 minutos)
fuente
Utilice el siguiente bloque de código en su archivo de inclusión que se cargó en cada página.
fuente
Usa esta clase por 30 minutos
fuente
Usando marca de tiempo ...
He usado 20 segundos para expirar la sesión usando la marca de tiempo .
Si necesita 30 minutos, agregue 1800 (30 minutos en segundos) ...
fuente
Puede usar directamente una base de datos para hacerlo como alternativa. Utilizo una función DB para hacerlo que llamo chk_lgn.
Verifique las verificaciones de inicio de sesión para ver si han iniciado sesión o no y, al hacerlo, establece la marca de fecha y hora de la verificación como la última activa en la fila / columna db del usuario.
También hago la verificación de tiempo allí. Esto funciona para mí por el momento, ya que uso esta función para cada página.
PD: Nadie que haya visto había sugerido una solución de DB pura.
fuente
Cómo PHP maneja las sesiones es bastante confuso para que los principiantes lo entiendan. Esto podría ayudarlos al dar una visión general de cómo funcionan las sesiones: cómo funcionan las sesiones (controladores de sesión personalizados)
fuente
Simplemente almacene la hora actual y si supera los 30 minutos comparando, destruya la sesión actual.
fuente