¿Cómo expiro una sesión de PHP después de 30 minutos?

Necesito mantener viva una sesión durante 30 minutos y luego destruirla.

preguntado el 06 de febrero de 09 a las 11:02

Tenga en cuenta que al menos dos configuraciones son cruciales para establecer la hora de la 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 tener una certeza total y 100% de permitir tiempos prolongados, también puede ser necesario configurar session.save_path, debido a la variación del tiempo de limpieza controlado por el sistema operativo en el directorio / tmp donde los archivos de sesión se almacenan de forma predeterminada. -

No entiendo por qué quiere caducar la sesión. Si le preocupa que el usuario abandone su computadora sin cerrar la sesión y un usuario no autorizado se apodere de su computadora, la expiración de la sesión en su sitio no evitará que el secuestrador acceda a los archivos de la víctima en el disco. -

No está claro lo que estás preguntando aquí. ¿Quiere decir que desea implementar un tiempo de espera de inactividad estricto (actualmente PHP 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 consejo bastante malo para cualquier problema; en ambos casos, la lógica debe implementarse con un controlador de sesión personalizado. -

16 Respuestas

Debe implementar su propio tiempo de espera de sesión. Ambas opciones mencionadas por otros (session.gc_maxlifetime y session.cookie_lifetime) no son fiables. 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 se verán como "basura" y se limpiarán. 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 dividido por session.gc_divisor. Y usando los valores predeterminados para esas opciones (1 y 100 respectivamente), la probabilidad es solo del 1%.

Bueno, simplemente podría 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 usa PHP por defecto session.save_handler archivos, 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 fecha de la última modificación del archivo y no en la fecha del último 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 en 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 utilizado mtime (fecha de modificación) en lugar de atime. Por lo tanto, no tendrá problemas con los sistemas de archivos donde el seguimiento de tiempo no está disponible.

Por lo tanto, también puede ocurrir que se elimine un archivo de datos de sesión mientras que la sesión en sí 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. […]

Sí, eso es correcto. Esto solo afecta la vida útil de la cookie y la sesión en sí puede seguir siendo válida. Pero es tarea del servidor invalidar una sesión, no del cliente. Entonces esto no ayuda en nada. De hecho, habiendo session.cookie_lifetime establecido en 0 haría que la cookie de la sesión fuera un verdadero cookie de sesión que solo es válido hasta que se cierra 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, 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 la 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 antes de tiempo.

También puede utilizar una marca de tiempo adicional para regenerar el ID de sesión periódicamente para evitar ataques a sesiones como fijación de 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 vencimiento personalizado (1800 en este ejemplo);
  • si desea caducar la sesión después de 30 minutos de actividad en lugar de después de 30 minutos desde el comienzo, también necesitarás usar setcookie con un vencimiento de time()+60*30 para mantener activa la cookie de sesión.

Respondido 25 Feb 15, 07:02

¿Cómo podría modificar esto si quisiera marcar "tiempo inactivo"? En otras palabras, el usuario inicia sesión y, mientras continúe usando el sitio, no lo cerrará. Sin embargo, si están inactivos durante 30 minutos, ¿se cerrará la sesión? - Metrópoli

@Metropolis: usa algo como $_SESSION['LAST_ACTIVITY'] similar a $_SESSION['CREATED'] donde almacena la hora de la última actividad del usuario pero actualiza ese valor con cada solicitud. Ahora bien, 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

@Metrópoli: session_unset hace lo mismo que $_SESSION = array(). - Gumbo

@Gumbo - Estoy un poco confundido, ¿no debería usar su 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 aún es válida, al menos si la configuración ini es de 24 minutos estándar. ¿O me estoy perdiendo algo? - Jeroen

@jeron: Sí, deberías. Pero tenga en cuenta que session.gc_maxlifetime depende de la última fecha de modificación del archivo si el controlador de guardado de la sesión files se utiliza. Entonces session.gc_maxlifetime debe ser al menos igual a la vida útil de este controlador de vencimiento personalizado. - Gumbo

Manera simple de caducidad de la sesión PHP en 30 minutos.

Nota: si desea cambiar la hora, simplemente cambie el 30 con la hora deseada 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>
    <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!";
        }
    }
?>

Página de inicio.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
        }
    }
?>

Salir.php

<?php
    session_start();
    session_destroy();
    header('Location: http://localhost/somefolder/login.php');
?>

Respondido 24 ago 18, 13:08

Combinar lógica y presentación es desaconsejable en esta época en la que MVC es la norma. - bcosca

Tal vez me esté perdiendo algo elemental sobre las sesiones, pero ¿de qué sirve esto si el sistema operativo destruye las sesiones cada 30 minutos? - usuario336063

@stillstanding Habla por ti mismo [sonrisa] Veo MVC como una abominación. - usuario336063

¿MVC es una buena idea incluso cuando el proyecto es pequeño, con un solo programador? Siento que debería estar haciendo mis propios proyectos en el modelo MVC (o resolver el problema ENTONCES convertirlo en MVC) pero con la falta de experiencia con MVC simplemente se convierte en un bloqueo mental "¿Cómo hago este MVC?" y una distracción del objetivo / problema inicial que requiere una solución. - SrVimes

@bsosca, como muchos aquí deberían, debería dedicar más tiempo a preocuparse por las soluciones a los problemas y permitir que el OP lo resuelva que secuestrar una pregunta para hacer algún punto que crea que es válido ;-) - Mattt

¿Esto es para cerrar la sesión del usuario después de un tiempo establecido? Establecer la hora de creación de la sesión (o una hora de vencimiento) cuando se registra, 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']);
}

Edit: Tengo la sensación de que te refieres a otra cosa.

Puede desechar sesiones después de una vida útil determinada mediante el session.gc_maxlifetime ajuste ini:

Edit: ini_set ('sesión.gc_maxlifetime', 60 * 30);

respondido 03 nov., 13:13

session.gc-maxlifetime es probablemente la mejor manera de hacerlo. - Señor de poder

Hay algunos problemas con la duración de la cookie de sesión, en particular, depende del cliente para hacerla cumplir. La duración de la cookie está ahí para permitir que el cliente limpie las cookies inútiles / caducadas, no debe confundirse con nada relacionado con la seguridad. - Jacco

Lo es gc_maxlifetime or gc-maxlifetime. ¿Admite guiones bajos y guiones? - mike causante

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

Respondido 07 Oct 14, 04:10

Bueno, entiendo que las respuestas anteriores son correctas pero están en el nivel de la aplicación, ¿por qué no usamos simplemente .htaccess archivo para establecer la hora de caducidad?

<IfModule mod_php5.c>
    #Session timeout
    php_value session.cookie_lifetime 1800
    php_value session.gc_maxlifetime 1800
</IfModule>

Respondido 15 Jul 15, 07:07

La respuesta de @ Lode da una explicación perfecta de por qué esta respuesta no es confiable no debe usarse. - emix

if (isSet($_SESSION['started'])){
    if((mktime() - $_SESSION['started'] - 60*30) > 0){
        //Logout, destroy session, etc.
    }
}
else {
    $_SESSION['started'] = mktime();
}

Respondido 10 Abr '14, 20:04

Use el session_set_cookie_paramsfunciton para hacer esto.

Es necesario llamar a esta función antes session_start() llamada.

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

contestado el 01 de mayo de 17 a las 14:05

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 'tiempo'.

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 será destruida (Nota: Esta función usa una clase de base de datos para conectarse y consultar la base de datos, por supuesto que también podría 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;
}

contestado el 26 de mayo de 14 a las 12:05

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 se encuentra dentro de la ventana de tiempo permitida (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
}
?>

contestado el 21 de mayo de 15 a las 12:05

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();

Respondido 26 ago 16, 07:08

La forma en que PHP maneja las sesiones es bastante confusa de entender para los principiantes. Esto podría ayudarlos al brindarles una descripción general de cómo funcionan las sesiones: cómo funcionan las sesiones (controladores de sesión personalizados)

contestado el 31 de mayo de 20 a las 21:05

Utilice esta clase durante 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");
    }
}

Respondido el 27 de diciembre de 18 a las 10:12

Usando la 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 caducar la sesión usando la marca de tiempo.

Si necesita 30 min agregue 1800 (30 min en segundos) ...

Respondido 05 Jul 18, 15:07

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 de la base de datos 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 yo hubiera visto había sugerido una solución DB pura.

respondido 29 mar '19, 05:03

Esto fue una revelación para mí, lo que Christopher Kramer escribió en 2014 en https://www.php.net/manual/en/session.configuration.php#115842

En sistemas debian (basados ​​en), cambiar session.gc_maxlifetime en tiempo de ejecución no tiene ningún efecto real. Debian deshabilita el recolector de basura propio de PHP configurando session.gc_probability = 0. En su lugar, tiene un cronjob que se ejecuta cada 30 minutos (consulte /etc/cron.d/php5) que limpia las sesiones antiguas. Este cronjob básicamente busca en su php.ini y usa el valor de session.gc_maxlifetime allí para decidir qué sesiones limpiar (vea / usr / lib / php5 / maxlifetime). [...]

respondido 13 nov., 20:08

Simplemente guarde la hora actual y si supera los 30 minutos comparando, destruya la sesión actual.

Respondido el 24 de enero de 20 a las 08:01

La única vez que evaluaría eso es cuando usa la sesión, ¿verdad? - eric kramer

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.