Come faccio a scadere una sessione PHP dopo 30 minuti?


1047

Devo mantenere viva una sessione per 30 minuti e poi distruggerla.


35
Si noti che almeno due impostazioni sono cruciali per impostare il tempo della sessione e forse tre. I due sicuramente cruciali sono session.gc_maxlifetime e session.cookie_lifetime (dove 0 non è lo stesso di un numero lungo). Per una certezza completa al 100% di consentire tempi lunghi, potrebbe anche essere necessario impostare session.save_path, a causa della variazione del tempo di pulizia controllato dal sistema operativo nella directory / tmp in cui i file di sessione vengono archiviati per impostazione predefinita.
Kzqai,

1
Non capisco perché vuoi scadere la sessione. Se temi che l'utente lasci il suo computer senza disconnettersi e un utente non autorizzato subentri al suo computer, la scadenza della sessione sul tuo sito non impedirà al dirottatore di accedere ai file della vittima sul disco.
Gqqnbig,

Non è chiaro cosa stai chiedendo qui. Vuoi dire che vuoi implementare un duro timeout di inattività (attualmente PHP ti consentirà felicemente di usare una sessione che non è stata toccata per più di session.gc_maxlifetime) o intendi che vuoi limitare la sessione a 30 minuti indipendentemente da inattività? Francamente penso che la risposta accettata qui sia piuttosto un cattivo consiglio per entrambi i problemi - in entrambi i casi la logica dovrebbe essere implementata con un gestore di sessioni personalizzato.
symcbean,

Risposte:


1663

È necessario implementare un timeout di sessione autonomo. Entrambe le opzioni menzionate da altri ( session.gc_maxlifetime e session.cookie_lifetime ) non sono affidabili. Spiegherò le ragioni di ciò.

Primo:

session.gc_maxlifetime
session.gc_maxlifetime specifica il numero di secondi dopo i quali i dati saranno visti come "immondizia" e ripuliti. La garbage collection si verifica all'avvio della sessione.

Ma il Garbage Collector viene avviato solo con una probabilità di session.gc_probability divisa per session.gc_divisor . E usando i valori predefiniti per quelle opzioni (rispettivamente 1 e 100), la probabilità è solo dell'1%.

Bene, potresti semplicemente regolare questi valori in modo che il Garbage Collector venga avviato più spesso. Ma quando viene avviato il Garbage Collector, verificherà la validità di ogni sessione registrata. E questo è costoso.

Inoltre, quando si utilizzano i file session.save_handler predefiniti di PHP , i dati della sessione vengono archiviati in file in un percorso specificato in session.save_path . Con quel gestore di sessione, l'età dei dati della sessione viene calcolata sull'ultima data di modifica del file e non sull'ultima data di accesso:

Nota: se si utilizza il gestore di sessioni basato su file predefinito, il file system deve tenere traccia dei tempi di accesso (atime). Windows FAT non è così, dovrai trovare un altro modo per gestire la raccolta di dati inutili della sessione se sei bloccato con un file system FAT o qualsiasi altro file system in cui il monitoraggio atime non è disponibile. Da PHP 4.2.3 ha usato mtime (data modificata) anziché atime. Quindi, non avrai problemi con i filesystem in cui il monitoraggio atime non è disponibile.

Quindi potrebbe anche accadere che un file di dati di sessione venga eliminato mentre la sessione stessa è ancora considerata valida perché i dati della sessione non sono stati aggiornati di recente.

E secondo:

session.cookie_lifetime
session.cookie_lifetime specifica la durata del cookie in secondi che viene inviato al browser. [...]

Sì, è giusto. Ciò influisce solo sulla durata dei cookie e la sessione stessa potrebbe essere ancora valida. Ma è compito del server invalidare una sessione, non il client. Quindi questo non aiuta nulla. In effetti, avere session.cookie_lifetime impostato su 0renderebbe il cookie della sessione un vero cookie di sessione valido solo fino alla chiusura del browser.

Conclusione / migliore soluzione:

La soluzione migliore è implementare un timeout di sessione personalizzato. Utilizzare un semplice timestamp che indica l'ora dell'ultima attività (ad es. Richiesta) e aggiornarla ad ogni richiesta:

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

L'aggiornamento dei dati della sessione con ogni richiesta modifica anche la data di modifica del file della sessione in modo che la sessione non venga rimossa prematuramente dal Garbage Collector.

È inoltre possibile utilizzare un timestamp aggiuntivo per rigenerare periodicamente l'ID sessione per evitare attacchi a sessioni come la fissazione della sessione :

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
}

Appunti:

  • session.gc_maxlifetime dovrebbe essere almeno uguale alla durata di questo gestore di scadenza personalizzato (1800 in questo esempio);
  • se si desidera far scadere la sessione dopo 30 minuti di attività anziché dopo 30 minuti dall'inizio , è necessario utilizzare anche setcookieuna scadenza time()+60*30per mantenere attivo il cookie di sessione.

3
Come potresti alterarlo se volessi controllare il "tempo inattivo"? In altre parole, l'utente accede e fintanto che continua a utilizzare il sito, non verrà disconnesso. Tuttavia, se rimangono inattivi per 30 minuti, li disconnettono?
Metropolis,

14
@Metropolis: usa qualcosa di $_SESSION['LAST_ACTIVITY']simile a $_SESSION['CREATED']dove memorizzi l'ora dell'ultima attività dell'utente ma aggiorni quel valore con ogni richiesta. Ora se la differenza tra quell'ora e l'ora corrente è maggiore di 1800 secondi, la sessione non è stata utilizzata per più di 30 minuti.
Gumbo,

3
@Metropolis: session_unsetfa lo stesso di $_SESSION = array().
Gumbo,

14
@Gumbo - Sono un po 'confuso, non dovresti usare il tuo codice in combinazione con ini_set('session.gc-maxlifetime', 1800)? Altrimenti le informazioni sulla sessione potrebbero essere distrutte mentre la sessione dovrebbe essere ancora valida, almeno se l'impostazione ini è i 24 minuti standard. Oppure mi sfugge qualcosa?
jeroen,

10
@jeron: Sì, dovresti. Si noti che session.gc_maxlifetime dipende dall'ultima data di modifica del file se filesviene utilizzato il gestore di salvataggio della sessione . Quindi session.gc_maxlifetime dovrebbe essere almeno uguale al tempo di vita di questo gestore di scadenza personalizzato.
Gumbo,

135

Modo semplice di scadenza della sessione PHP in 30 minuti.

Nota: se si desidera modificare l'ora, basta cambiare il 30 con l'ora desiderata e non cambiare * 60: questo darà i minuti.


In minuti: (30 * 60)
In giorni: (n * 24 * 60 * 60) n = no di giorni


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!";
        }
    }
?>

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
        }
    }
?>

logout.php

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

42
La combinazione di logica e presentazione è sconsigliata ai giorni nostri, quando MVC è la norma.
bcosca,

Forse mi manca qualcosa di elementare sulle sessioni, ma a che serve fare questo se le sessioni vengono distrutte dal sistema operativo ogni 30 minuti?

25
@stillstanding Parla per te [sorridi] Vedo MVC come un abominio.

2
MVC è una buona idea anche quando il progetto è piccolo, con un solo programmatore? Mi sento come se dovessi realizzare i miei progetti nel modello MVC (o risolvere il problema POI farlo MVC) ma con una mancanza di esperienza con MVC diventa solo un blocco mentale "Come faccio a creare questo MVC?" e una distrazione dall'obiettivo / problema iniziale che richiede una soluzione.
MrVimes,

@stillstanding un'altra menzione è che sulle Login.phpintestazioni vengono inviati DOPO il contenuto, il che è male.
machineaddict,

43

Questo per disconnettere l'utente dopo un tempo prestabilito? L'impostazione del tempo di creazione della sessione (o un tempo di scadenza) quando è registrato, e quindi il controllo che su ogni caricamento della pagina potrebbe gestirlo.

Per esempio:

$_SESSION['example'] = array('foo' => 'bar', 'registered' => time());

// later

if ((time() - $_SESSION['example']['registered']) > (60 * 30)) {
    unset($_SESSION['example']);
}

Modifica: ho la sensazione che intendi qualcos'altro però.

Puoi eliminare le sessioni dopo una certa durata utilizzando l' session.gc_maxlifetimeimpostazione INI:

Modifica: ini_set ('session.gc_maxlifetime', 60 * 30);


1
session.gc-maxlifetime è probabilmente il modo migliore di procedere.
Powerlord,

2
Esistono alcuni problemi con la durata del cookie di sessione, in particolare dipende dal fatto che il client lo imponga. La durata dei cookie è lì per consentire al client di ripulire i cookie inutili / scaduti, non deve essere confuso con nulla di legato alla sicurezza.
Jacco,

È gc_maxlifetimeo gc-maxlifetime. Supporta sia trattini bassi che trattini?
Mike Causer,

24

Questo post mostra un paio di modi per controllare il timeout della sessione: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

IMHO la seconda opzione è una bella soluzione:

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

19

Bene capisco che le risposte di aboves sono corrette ma sono a livello di applicazione, perché non usiamo semplicemente il .htaccessfile per impostare il tempo di scadenza?

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

1
La risposta di @ Lode fornisce una spiegazione perfetta del perché questa risposta non è affidabile non deve essere utilizzata.
emix

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


11

In realtà è facile con una funzione come la seguente. Utilizza il nome della tabella del database 'sessioni' con i campi 'id' e 'time'.

Ogni volta che l'utente visita nuovamente il tuo sito o servizio, dovresti invocare questa funzione per verificare se il suo valore di ritorno è VERO. Se è FALSO l'utente è scaduto e la sessione verrà distrutta (Nota: questa funzione utilizza una classe di database per connettersi e interrogare il database, ovviamente potresti farlo anche all'interno della tua funzione o qualcosa del genere):

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

9

Memorizza un timestamp nella sessione


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

Ora, controlla se il timestamp rientra nella finestra temporale consentita (1800 secondi è 30 minuti)

<?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
}
?>

8

Utilizzare il seguente blocco di codice nel file include che è stato caricato in ogni pagina.

$expiry = 1800 ;//session expiry required after 30 mins
    if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
        session_unset();
        session_destroy();
    }
    $_SESSION['LAST'] = time();

1

Usa questa lezione per 30 minuti

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

0

Utilizzo del timestamp ...

<?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>";
    }
}
?>

Ho usato 20 secondi per scadere la sessione usando il timestamp .

Se hai bisogno di 30 minuti aggiungi 1800 (30 minuti in secondi) ...


0

Puoi usare direttamente un DB per farlo in alternativa. Uso una funzione DB per farlo che chiamo chk_lgn.

Controlla i controlli di accesso per vedere se sono connessi o meno e, in tal modo, imposta il timestamp della data dell'assegno come ultimo attivo nella riga / colonna del db dell'utente.

Faccio anche il controllo del tempo lì. Questo funziona per me per il momento in quanto utilizzo questa funzione per ogni pagina.

PS Nessuno di quelli che avevo visto aveva suggerito una soluzione DB pura.



-1

Memorizza solo l'ora corrente e se supera i 30 minuti confrontando, distruggi la sessione corrente.


L'unica volta che lo valuteresti è quando usi la sessione, giusto?
Eric Kramer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.