Necesito mantener viva una sesión durante 30 minutos y luego destruirla.
Necesito mantener viva una sesión durante 30 minutos y luego destruirla.
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:
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 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:
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();
} else if (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);setcookie
una expiración de time()+60*30
para mantener activa la cookie de sesión.$_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.
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
<?php
session_start();
?>
<html>
<form name="form1" method="post">
<table>
<tr>
<td>Username</td>
<td><input type="text" name="text"></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="pwd"></td>
</tr>
<tr>
<td><input type="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!";
}
}
?>
<?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
}
}
?>
<?php
session_start();
session_destroy();
header('Location: http://localhost/somefolder/login.php');
?>
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:
$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());
// later
if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
unset($_SESSION['example']);
}
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);
gc_maxlifetime
o gc-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:
<?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 .htaccess
archivo para establecer el tiempo de caducidad?
<IfModule mod_php5.c>
#Session timeout
php_value session.cookie_lifetime 1800
php_value session.gc_maxlifetime 1800
</IfModule>
Utilizar el session_set_cookie_params
función para hacer esto.
Es necesario llamar a esta función antes session_start()
llamar.
Prueba esto:
$lifetime = strtotime('+30 minutes', 0);
session_set_cookie_params($lifetime);
session_start();
Ver más en: http://php.net/manual/function.session-set-cookie-params.php
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 succesfully
if (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;
}
Almacenar una marca de tiempo en la sesión
<?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
}
?>
Utilice el siguiente bloque de código en su archivo de inclusión que se cargó en cada página.
$expiry = 1800 ;//session expiry required after 30 mins
if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
session_unset();
session_destroy();
}
$_SESSION['LAST'] = time();
Usa esta clase por 30 minutos
class Session{
public static function init(){
ini_set('session.gc_maxlifetime', 1800) ;
session_start();
}
public static function set($key, $val){
$_SESSION[$key] =$val;
}
public static function get($key){
if(isset($_SESSION[$key])){
return $_SESSION[$key];
} else{
return false;
}
}
public static function checkSession(){
self::init();
if(self::get("adminlogin")==false){
self::destroy();
header("Location:login.php");
}
}
public static function checkLogin(){
self::init();
if(self::get("adminlogin")==true){
header("Location:index.php");
}
}
public static function destroy(){
session_destroy();
header("Location:login.php");
}
}
Usando marca de tiempo ...
<?php
if (!isset($_SESSION)) {
$session = session_start();
}
if ($session && !isset($_SESSION['login_time'])) {
if ($session == 1) {
$_SESSION['login_time']=time();
echo "Login :".$_SESSION['login_time'];
echo "<br>";
$_SESSION['idle_time']=$_SESSION['login_time']+20;
echo "Session Idle :".$_SESSION['idle_time'];
echo "<br>";
} else{
$_SESSION['login_time']="";
}
} else {
if (time()>$_SESSION['idle_time']){
echo "Session Idle :".$_SESSION['idle_time'];
echo "<br>";
echo "Current :".time();
echo "<br>";
echo "Session Time Out";
session_destroy();
session_unset();
} else {
echo "Logged In<br>";
}
}
?>
He usado 20 segundos para expirar la sesión usando la marca de tiempo .
Si necesita 30 minutos, agregue 1800 (30 minutos en segundos) ...
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.
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)
Simplemente almacene la hora actual y si supera los 30 minutos comparando, destruya la sesión actual.