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

1047

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

À M
la source
35
Veuillez noter qu'au moins deux paramètres sont essentiels pour définir l'heure de la session, et peut-être trois. Les deux certainement cruciaux sont session.gc_maxlifetime et session.cookie_lifetime (où 0 n'est pas la même chose qu'un certain nombre long). Pour une certitude complète et à 100% d'autoriser de longs délais, il peut également être nécessaire de définir session.save_path, en raison de la variation du temps de nettoyage contrôlé par le système d'exploitation dans le répertoire / tmp où les fichiers de session sont stockés par défaut.
Kzqai
1
Je ne comprends pas pourquoi vous souhaitez expirer la session. Si vous craignez que l'utilisateur quitte son ordinateur sans se déconnecter et qu'un utilisateur non autorisé prenne le contrôle de son ordinateur, l'expiration de la session sur votre site n'empêchera pas le pirate de l'air d'accéder aux fichiers de la victime sur le disque.
Gqqnbig
Ce n'est pas clair ce que vous demandez ici. Voulez-vous dire que vous souhaitez implémenter un délai d'inactivité dur (actuellement PHP vous laissera volontiers utiliser une session qui n'a pas été touchée depuis plus de session.gc_maxlifetime) ou voulez-vous dire que vous voulez limiter la session à 30 minutes indépendamment de inactivité? Franchement, je pense que la réponse acceptée ici est un mauvais conseil pour l'un ou l'autre problème - dans les deux cas, la logique devrait être implémentée avec un gestionnaire de session personnalisé.
symcbean

Réponses:

1663

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

Première:

session.gc_maxlifetime
session.gc_maxlifetime spécifie le nombre de secondes après lesquelles les données seront considérées comme des «ordures» et nettoyées. Le garbage collection se produit au début de la session.

Mais le garbage collector n'est démarré qu'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 garbage collector soit démarré plus souvent. Mais lorsque le garbage collector 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 session sont stockées dans des fichiers dans un chemin spécifié dans session.save_path . Avec ce gestionnaire de session, l'âge des données de session est calculé à la dernière date de modification du fichier et non à la dernière date d'accès:

Remarque: Si vous utilisez le gestionnaire de session basé sur des fichiers par défaut, votre système de fichiers doit garder une trace des temps d'accès (atime). Windows FAT ne le fait pas, vous devrez donc trouver une autre façon de gérer le ramasse-miettes 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 a utilisé mtime (date modifiée) au lieu de atime. Ainsi, vous n'aurez pas de problèmes avec les systèmes de fichiers où le suivi atime n'est pas disponible.

Il peut donc en outre se produire 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 session n'ont pas été mises à jour récemment.

Et deuxieme:

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

Oui c'est vrai. Cela n'affecte que la durée de vie du cookie 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. Donc cela n'aide en rien. En fait, avoir session.cookie_lifetime défini sur 0ferait du cookie de la session un véritable cookie de session qui n'est valide que jusqu'à la fermeture du navigateur.

Conclusion / meilleure solution:

La meilleure solution consiste à implémenter votre propre délai d'expiration de session. Utilisez un horodatage simple qui indique l'heure de la dernière activité (c'est-à-dire la demande) et mettez-le à jour avec chaque demande:

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 garbage collector.

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

Remarques:

  • 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 souhaitez expirer la session après 30 minutes d' activité au lieu de 30 minutes depuis le début , vous devrez également utiliser setcookieavec une expiration de time()+60*30pour conserver le cookie de session actif.
Gombo
la source
3
Comment pourriez-vous modifier cela si vous vouliez vérifier le «temps inactif»? En d'autres termes, l'utilisateur se connecte et tant qu'il continue à utiliser le site, il ne le déconnecte pas. Cependant, s'ils sont inactifs pendant 30 minutes, cela les déconnectera-t-il?
Metropolis
14
@Metropolis: utilisez quelque chose comme $_SESSION['LAST_ACTIVITY']similaire à l' $_SESSION['CREATED']endroit où vous stockez l'heure de la dernière activité de l'utilisateur, mais mettez à jour cette valeur à chaque demande. Maintenant, si la différence de cette heure à l'heure actuelle est supérieure à 1800 secondes, la session n'a pas été utilisée pendant plus de 30 minutes.
Gumbo
3
@Metropolis: session_unsetfait la même chose que $_SESSION = array().
Gumbo
14
@Gumbo - Je suis un peu confus, ne devriez-vous pas utiliser votre code en combinaison avec ini_set('session.gc-maxlifetime', 1800)? Sinon, vos informations de session pourraient être détruites alors que votre session est toujours censée être valide, au moins si le paramètre ini est le standard de 24 minutes. Ou est-ce que je manque quelque chose?
jeroen
10
@jeron: Oui, vous devriez. Mais notez que session.gc_maxlifetime dépend de la dernière date de modification du fichier si le gestionnaire de sauvegarde de session filesest utilisé. La session.gc_maxlifetime doit donc être au moins égale à la durée de vie de ce gestionnaire d'expiration personnalisé.
Gumbo
135

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

Remarque: si vous voulez changer l'heure, changez simplement le 30 avec l'heure souhaitée et ne changez pas * 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');
?>
Rafee
la source
42
La combinaison de la logique et de la présentation est mal conseillée de nos jours où le MVC est la norme.
bcosca
Peut-être que je manque quelque chose d'élémentaire sur les sessions, mais à quoi cela sert-il si les sessions sont détruites toutes les 30 minutes par le système d'exploitation?
25
@stillstanding Parlez pour vous [sourire] Je considère MVC comme une abomination.
2
MVC est-il une bonne idée même lorsque le projet est petit, avec un seul programmeur? J'ai l'impression que je devrais faire mes propres projets dans le modèle MVC (ou résoudre le problème ALORS en faire MVC) mais avec un manque d'expérience avec MVC cela devient juste un blocage mental "Comment puis-je faire ce MVC?" et une distraction de l'objectif / problème initial nécessitant une solution.
MrVimes
@ encore une autre mention est que les en- Login.phptêtes sont envoyés APRÈS le contenu, ce qui est mauvais.
machineaddict
43

Est-ce pour déconnecter l'utilisateur après un temps défini? Définir l'heure de création de la session (ou une heure d'expiration) lors de son enregistrement, puis vérifier que sur chaque chargement de page pourrait gérer cela.

Par exemple:

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

// later

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

Edit: J'ai le sentiment que vous voulez dire autre chose cependant.

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

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

Ross
la source
1
session.gc-maxlifetime est probablement la meilleure solution.
Powerlord
2
Il y a quelques problèmes avec la durée de vie du cookie de session, notamment, il dépend du client pour l'appliquer. La durée de vie du cookie est là pour permettre au client de nettoyer les cookies inutiles / expirés, il ne doit pas être confondu avec quoi que ce soit lié à la sécurité.
Jacco
Est-ce gc_maxlifetimeou gc-maxlifetime. Prend-il en charge les traits de soulignement et les tirets?
Mike Causer
24

Cette publication montre quelques façons de contrôler le délai d'expiration de la session: http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions

À mon humble avis, la deuxième option est une bonne solution:

<?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);
    }
}
Pablo Pazos
la source
19

Eh bien, je comprends que les réponses ci-dessus sont correctes, mais elles sont au niveau de l'application, pourquoi ne pas simplement utiliser le .htaccessfichier 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>
Touqeer Shafi
la source
1
La réponse de @ Lode explique parfaitement pourquoi cette réponse n'est pas fiable ne doit pas être utilisée.
emix
15
if (isSet($_SESSION['started'])){
    if((mktime() - $_SESSION['started'] - 60*30) > 0){
        //Logout, destroy session, etc.
    }
}
else {
    $_SESSION['started'] = mktime();
}
middus
la source
15

Utilisez le session_set_cookie_params fonction pour faire cela.

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

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

Wallace Maxters
la source
11

C'est en fait facile avec une fonction comme la suivante. Il utilise le nom de 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 invoquer cette fonction pour vérifier si sa valeur de retour est VRAIE. Si elle est FAUX, 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, bien sûr, vous pouvez également le faire à l'intérieur de votre fonction ou quelque chose comme ça):

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;
}
Torsten Barthel
la source
9

Enregistrer 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 soit 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
}
?>
Alpesh Rathod
la source
8

Veuillez utiliser le bloc de code suivant dans votre fichier include qui s'est 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();
lnepal
la source
1

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");
    }
}
Amranur Rahman
la source
0

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 expirer la session en utilisant l'horodatage .

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

Sarvan Kumar
la source
0

Vous pouvez directement utiliser une base de données pour le faire comme alternative. J'utilise une fonction DB pour ce faire que j'appelle chk_lgn.

Vérifiez les vérifications de connexion pour voir si elles sont connectées ou non et, ce faisant, elle définit l'horodatage de la date du dernier contrôle comme actif dans la ligne / colonne db de l'utilisateur.

J'y fais aussi le contrôle horaire. Cela fonctionne pour moi pour le moment car j'utilise cette fonction pour chaque page.

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

JSG
la source
-1

Il suffit de stocker l'heure actuelle et si elle dépasse 30 minutes en comparant puis détruisez la session en cours.

Narendra Sharma
la source
La seule fois où vous évalueriez cela, c'est lors de l'utilisation de la session, non?
Eric Kramer