web-dev-qa-db-fra.com

Comment puis-je expirer un PHP session après 30 minutes?

Je dois garder une session active pendant 30 minutes, puis la détruire. 

969
Tom

Vous devez implémenter votre propre délai d'attente de session. Les deux options mentionnées par d'autres ( session.gc_maxlifetime et session.cookie_lifetime ) ne sont pas fiables. Je vais expliquer les raisons pour cela.

D'abord:

session.gc_maxlifetime
session.gc_maxlifetime spécifie le nombre de secondes après lequel les données seront considérées comme des "ordures" et nettoyées. Le ramassage des ordures a lieu au début de la session.

Mais le ramasse-miettes est uniquement démarré avec une probabilité de session.gc_probability ) == divisée par session.gc_divisor . Et en utilisant les valeurs par défaut pour ces options (1 et 100 respectivement), la chance n’est que de 1%.

Eh bien, vous pouvez simplement ajuster ces valeurs pour que le ramasse-miettes démarre plus souvent. Mais lorsque le ramasse-miettes est démarré, il vérifie la validité de chaque session enregistrée. Et cela coûte cher.

De plus, lorsque vous utilisez les fichiers --- session.save_handler par défaut de PHP, les données de la session sont stockées dans des fichiers dans un chemin spécifié entre session.save_path = . Avec ce gestionnaire de session, l'âge des données de session est calculé sur la dernière date de modification du fichier et non sur la dernière date d'accès:

Remarque: Si vous utilisez le gestionnaire de session par défaut basé sur fichier, votre système de fichiers doit garder trace des temps d'accès (atime). Windows FAT ne vous oblige pas à trouver un autre moyen de gérer la récupération de mémoire de votre session si vous êtes bloqué avec un système de fichiers FAT ou tout autre système de fichiers où le suivi atime n'est pas disponible. Depuis PHP 4.2.3, il utilise mtime (date de modification) au lieu de atime. Ainsi, vous n’aurez aucun problème avec les systèmes de fichiers où le suivi atime n’est pas disponible.

Par conséquent, il peut également arriver qu'un fichier de données de session soit supprimé alors que la session elle-même est toujours considérée comme valide car les données de la session n'ont pas été mises à jour récemment.

Et en second lieu:

session.cookie_lifetime
session.cookie_lifetime spécifie la durée de vie du cookie, en secondes, envoyée au navigateur. […]

Oui c'est vrai. Cela n'affecte que la durée de vie des cookies et la session elle-même peut toujours être valide. Mais c'est la tâche du serveur d'invalider une session, pas le client. Cela n'aide donc rien. En fait, si vous avez configuré session.cookie_lifetime sur 0, le cookie de la session deviendra un véritable cookie de session valide uniquement jusqu'à la fermeture du navigateur.

Conclusion/meilleure solution:

La meilleure solution consiste à implémenter votre propre délai d'attente de session. Utilisez un horodatage simple indiquant l'heure de la dernière activité (c'est-à-dire une requête) et mettez-le à jour à chaque requête:

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 mise à jour des données de session à chaque demande modifie également la date de modification du fichier de session afin que la session ne soit pas supprimée prématurément par le récupérateur de mémoire.

Vous pouvez également utiliser un horodatage supplémentaire pour régénérer périodiquement l'ID de session afin d'éviter des attaques sur des sessions telles que fixation de session :

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
}

Notes:

  • session.gc_maxlifetime doit être au moins égal à la durée de vie de ce gestionnaire d'expiration personnalisé (1800 dans cet exemple);
  • si vous voulez que la session expire après 30 minutes de activité au lieu de après 30 minutes depuis le début, vous devez également utiliser setcookie avec une expiration de time()+60*30 pour garder le cookie de session actif.
1605
Gumbo

Moyen simple d’expiration de la session PHP en 30 minutes.

Remarque: si vous souhaitez modifier l'heure, il vous suffit de modifier l'heure 30 avec l'heure souhaitée et de ne pas changer * 60: cela donnera les minutes.


En minutes: (30 * 60) 
En jours: (n * 24 * 60 * 60) n = nombre de jours 


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');
?>
121
Rafee

S'agit-il de déconnecter l'utilisateur après une heure donnée? Définir l'heure de création de la session (ou une date d'expiration) lors de son enregistrement, puis vérifier que le chargement de chaque page peut le gérer.

Par exemple.:

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

// later

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

Edit: J'ai l'impression que vous voulez dire autre chose.

Vous pouvez supprimer des sessions après une certaine durée de vie en utilisant le paramètre session.gc_maxlifetime ini:

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

36
Ross

Cet article montre deux manières de contrôler le délai d'expiration de la session: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

IMHO la deuxième option est une solution de Nice:

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

Je comprends bien que les réponses ci-dessus sont correctes mais qu’elles se situent au niveau de l’application. Pourquoi ne pas simplement utiliser le fichier .htaccess pour définir le délai d’expiration?

<IfModule mod_php5.c>
    #Session timeout
    php_value session.cookie_lifetime 1800
    php_value session.gc_maxlifetime 1800
</IfModule>
17
Touqeer Shafi
if (isSet($_SESSION['started'])){
    if((mktime() - $_SESSION['started'] - 60*30) > 0){
        //Logout, destroy session, etc.
    }
}
else {
    $_SESSION['started'] = mktime();
}
14
middus

Utilisez le session_set_cookie_paramsfunciton pour faire ceci.

Est-il nécessaire d'appeler cette fonction avant l'appel session_start().

Essaye ça:

$lifetime = strtotime('+30 minutes', 0);

session_set_cookie_params($lifetime);

session_start();

Voir plus dans: http://php.net/manual/function.session-set-cookie-params.php

13
Wallace Maxters

C'est en fait facile avec une fonction comme celle-ci. Il utilise le nom de la table de base de données 'sessions' avec les champs 'id' et 'time'.

Chaque fois que l'utilisateur visite à nouveau votre site ou service, vous devez appeler cette fonction pour vérifier si sa valeur de retour est TRUE. Si la valeur est FALSE, l'utilisateur a expiré et la session sera détruite (Remarque: cette fonction utilise une classe de base de données pour se connecter et interroger la base de données. Vous pouvez bien sûr également le faire dans votre fonction ou quelque chose du genre):

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;
}
11
Torsten Barthel

Stocker un horodatage dans la session


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

Maintenant, vérifiez si l'horodatage est dans la fenêtre de temps autorisée (1800 secondes correspondent à 30 minutes)

<?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
Alpesh Rathod

Veuillez utiliser le bloc de code suivant dans votre fichier d’inclusion chargé dans toutes les pages.

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

Utilisez cette classe pendant 30 min

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
Amranur Rahman

Vous pouvez directement utiliser une base de données pour le faire à la place. J'utilise une fonction de base de données que j'appelle chk_lgn.

Vérifiez les vérifications de connexion pour voir si elles sont connectées ou non et, ce faisant, définit l'horodatage de la vérification comme dernière active dans la ligne/colonne de la base de données de l'utilisateur.

Je fais aussi la vérification du temps là-bas. Cela fonctionne pour moi pour le moment car j'utilise cette fonction pour chaque page.

P.S. Personne que j'avais vu n'avait suggéré une solution DB pure.

0
JSG

Utilisation de l'horodatage ...

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

J'ai utilisé 20 secondes pour terminer la session avec timestamp

Si vous avez besoin de 30 minutes, ajoutez 1800 (30 minutes en secondes) ...

0
Sarvan Kumar