Comment changer le timeout de session en PHP?

154

Je souhaite prolonger le délai d'expiration de la session en php

Je sais qu'il est possible de le faire en modifiant le fichier php.ini. Mais je n'y ai pas accès.

Alors, est-il possible de le faire uniquement avec du code php?

Oli
la source
1
En relation, ceci est dans php.ini, mais je pense que vous pouvez utiliser ini_set comme @matino a déclaré stackoverflow.com/questions/520237/...
J-Rou

Réponses:

324

Le délai d'expiration de session est une notion qui doit être implémentée dans le code si vous voulez des garanties strictes; c'est le seul moyen vous pouvez être absolument certain qu'aucune session ne survivra jamais après X minutes d'inactivité.

Si assouplir un peu cette exigence est acceptable et que vous êtes d'accord pour placer une limite inférieure au lieu d'une limite stricte à la durée, vous pouvez le faire facilement et sans écrire de logique personnalisée.

Commodité dans des environnements détendus: comment et pourquoi

Si vos sessions sont implémentées avec des cookies (ce qu'ils sont probablement), et si les clients ne sont pas malveillants, vous pouvez définir une limite supérieure sur la durée de la session en modifiant certains paramètres. Si vous utilisez la gestion de session par défaut de PHP avec les cookies, la configuration session.gc_maxlifetimeavec session_set_cookie_paramsdevrait fonctionner pour vous comme ceci:

// server should keep session data for AT LEAST 1 hour
ini_set('session.gc_maxlifetime', 3600);

// each client should remember their session id for EXACTLY 1 hour
session_set_cookie_params(3600);

session_start(); // ready to go!

Cela fonctionne en configurant le serveur pour conserver les données de session pendant au moins une heure d'inactivité et en indiquant à vos clients qu'ils doivent «oublier» leur identifiant de session après la même période. Ces deux étapes sont nécessaires pour obtenir le résultat attendu.

  • Si vous ne dites pas aux clients d'oublier leur identifiant de session après une heure (ou si les clients sont malveillants et choisissent d'ignorer vos instructions), ils continueront à utiliser le même identifiant de session et sa durée effective ne sera pas déterministe. Cela est dû au fait que les sessions dont la durée de vie a expiré côté serveur ne sont pas récupérées immédiatement mais uniquement chaque fois que la session GC démarre. .

    GC est un processus potentiellement coûteux, donc généralement la probabilité est plutôt faible voire nulle (un site Web recevant un grand nombre de visites renoncera probablement complètement au GC probabiliste et le programmera pour qu'il se produise en arrière-plan toutes les X minutes). Dans les deux cas (en supposant que les clients ne coopèrent pas), la limite inférieure de la durée de vie effective des sessions sera session.gc_maxlifetime, mais la limite supérieure sera imprévisible.

  • Si vous ne définissez session.gc_maxlifetimepas la même période, le serveur peut ignorer les données de session inactives antérieures à cela; dans ce cas, un client qui se souvient encore de son identifiant de session le présentera mais le serveur ne trouvera aucune donnée associée à cette session, se comportant effectivement comme si la session venait juste de démarrer.

Certitude dans les environnements critiques

Vous pouvez rendre les choses complètement contrôlables en utilisant une logique personnalisée pour placer également une limite supérieure sur l'inactivité de session; avec la limite inférieure d'en haut, cela donne un réglage strict.

Pour ce faire, enregistrez la limite supérieure avec le reste des données de session:

session_start(); // ready to go!

$now = time();
if (isset($_SESSION['discard_after']) && $now > $_SESSION['discard_after']) {
    // this session has worn out its welcome; kill it and start a brand new one
    session_unset();
    session_destroy();
    session_start();
}

// either new or old, it should live at most for another hour
$_SESSION['discard_after'] = $now + 3600;

Persistance de l'identifiant de session

Jusqu'à présent, nous ne nous sommes pas du tout préoccupés des valeurs exactes de chaque identifiant de session, mais uniquement de l'exigence que les données existent aussi longtemps que nous en avons besoin. Sachez que dans le cas (peu probable) où les identifiants de session vous importent, il faut veiller à les régénérer session_regenerate_idlorsque cela est nécessaire.

Jon
la source
Question: si appelez ceci, disons juste à chaque minute, augmentera-t-il sa limite? exemple à 10h00 je l'ai appelé pour que sa limite soit 11h00, après 1 miutes, 10h01, la limite sera-t-elle 11h01?
oneofakind
@oneofakind: Si vous appelez quoi exactement?
Jon
1
Ceux-ci: ini_set ('session.gc_maxlifetime', 3600); session_set_cookie_params (3600);
oneofakind
@oneofakind: Oui, mais seulement si vous appelez session_start()également (sinon aucun effet) et seulement si vous appelez toujours ces deux avant session_start(sinon cela gc_maxlifetimepourrait affecter toutes les sessions actuellement ouvertes, alors que session_set_cookie_paramscela ne peut affecter qu'une nouvelle session qui commence par la demande actuelle).
Jon
@Jon si j'appelle à nouveau session_start (), cela réinitialisera-t-il tout dans ma $ _SESSION? si vous entendez par «a le potentiel d'affecter toutes les sessions», comment cela? Merci pour la réponse.
oneofakind
33

Si vous utilisez la gestion de session par défaut de PHP, le seul moyen de modifier de manière fiable la durée de session sur toutes les plates-formes est de changer php.ini . En effet, sur certaines plates-formes, le ramasse-miettes est implémenté via un script qui s'exécute à chaque fois (un script cron ) qui lit directement depuis php.ini , et donc toute tentative de le modifier au moment de l'exécution, par exemple viaini_set() , n'est pas fiable et très probable ne fonctionnera pas.

Par exemple, dans les systèmes Debian Linux, le ramasse-miettes interne de PHP est désactivé par session.gc_probability=0défaut dans la configuration, et se fait à la place via /etc/cron.d/php, qui s'exécute à XX: 09 et XX: 39 (c'est-à-dire, chaque demi heure). Ce travail cron recherche les sessions antérieures à la session.gc_maxlifetime spécifiée dans la configuration et, le cas échéant, elles sont supprimées. En conséquence, dans ces systèmes ini_set('session.gc_maxlifetime', ...)est ignoré. Cela explique également pourquoi dans cette question: les sessions PHP expirent trop rapidement , l'OP avait des problèmes dans un hôte mais les problèmes ont cessé lors du passage à un hôte différent.

Donc, étant donné que vous n'avez pas accès à php.ini , si vous voulez le faire de manière portable, utiliser la gestion de session par défaut n'est pas une option. Apparemment, prolonger la durée de vie des cookies était suffisant pour votre hôte, mais si vous voulez une solution qui fonctionne de manière fiable même si vous changez d'hôtes, vous devez utiliser une alternative différente.

Les méthodes alternatives disponibles incluent:

  1. Définissez un gestionnaire de session (sauvegarde) différent en PHP pour enregistrer vos sessions dans un répertoire différent ou dans une base de données, comme spécifié dans PHP: Custom Session Handlers (manuel PHP) , de sorte que le travail cron ne l'atteigne pas, et seulement PHP un garbage collection interne a lieu. Cette option peut probablement utiliser ini_set()pour définir session.gc_maxlifetime mais je préfère simplement ignorer le paramètre maxlifetime dans mon gc()rappel et déterminer la durée de vie maximale par moi-même.

  2. Oubliez complètement la gestion de session interne PHP et implémentez votre propre gestion de session. Cette méthode présente deux inconvénients principaux: vous aurez besoin de vos propres variables de session globales, vous perdez donc l'avantage du$_SESSION superglobal, et elle a besoin de plus de code donc il y a plus d'opportunités pour les bogues et les failles de sécurité. Plus important encore, l'identifiant de session doit être généré à partir de nombres aléatoires ou pseudo-aléatoires sécurisés cryptographiquement pour éviter la prévisibilité de l'identifiant de session (conduisant à un éventuel détournement de session), et ce n'est pas si facile à faire avec PHP de manière portable. Le principal avantage est qu'il fonctionnera de manière cohérente sur toutes les plates-formes et que vous avez un contrôle total sur le code. C'est l'approche adoptée par exemple par le logiciel du forum phpBB (au moins la version 1; je ne suis pas sûr des versions plus récentes).

Il y a un exemple de (1) dans le documentation poursession_set_save_handler() . L'exemple est long mais je vais le reproduire ici, avec les modifications pertinentes nécessaires pour prolonger la durée de la session. Notez également l'inclusion de session_set_cookie_params()pour augmenter la durée de vie des cookies.

<?php
class FileSessionHandler
{

    private $savePath;
    private $lifetime;

    function open($savePath, $sessionName)
    {
        $this->savePath = 'my_savepath'; // Ignore savepath and use our own to keep it safe from automatic GC
        $this->lifetime = 3600; // 1 hour minimum session duration
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath, 0777);
        }

        return true;
    }

    function close()
    {
        return true;
    }

    function read($id)
    {
        return (string)@file_get_contents("$this->savePath/sess_$id");
    }

    function write($id, $data)
    {
        return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
    }

    function destroy($id)
    {
        $file = "$this->savePath/sess_$id";
        if (file_exists($file)) {
            unlink($file);
        }

        return true;
    }

    function gc($maxlifetime)
    {
        foreach (glob("$this->savePath/sess_*") as $file) {
            if (filemtime($file) + $this->lifetime < time() && file_exists($file)) { // Use our own lifetime
                unlink($file);
            }
        }

        return true;
    }
}

$handler = new FileSessionHandler();
session_set_save_handler(
    array($handler, 'open'),
    array($handler, 'close'),
    array($handler, 'read'),
    array($handler, 'write'),
    array($handler, 'destroy'),
    array($handler, 'gc')
    );

// the following prevents unexpected effects when using objects as save handlers
register_shutdown_function('session_write_close');

session_set_cookie_params(3600); // Set session cookie duration to 1 hour
session_start();
// proceed to set and retrieve values by key from $_SESSION

L'approche (2) est plus compliquée; en gros, vous devez réimplémenter toutes les fonctions de session par vous-même. Je n'entrerai pas dans les détails ici.

Pedro Gimeno
la source
Quelqu'un pourrait-il le confirmer?
Oli le
@Oli: Cela semble correct après une lecture superficielle. Vous voudrez peut-être également consulter stackoverflow.com/questions/520237/… , mais si vous n'avez pas accès à php.inivos options pratiques, elles sont sévèrement limitées.
Jon
De plus, sur Ubuntu 14, il semble /usr/lib/php5/maxlifetimene pas calculer une valeur inférieure à 24 minutes. Vous ne pouvez donc pas définir les délais d'expiration de votre session sur une valeur inférieure à cela.
Henry
"Oubliez complètement la gestion des sessions internes PHP et implémentez votre propre gestion de session." bon Dieu, c'est un conseil dangereux. Un cauchemar sécuritaire en résulterait inévitablement.
Kzqai
@Kzqai Je note également que "il a besoin de plus de code donc il y a plus d'opportunités pour les bogues et les failles de sécurité". Ce n'est pas un conseil, j'énumère les alternatives, mais si vous avez une suggestion pour l'améliorer, faites-le.
Pedro Gimeno
3

Ajouter un commentaire pour toute personne utilisant Plesk ayant des problèmes avec l'un des éléments ci-dessus car cela me rendait fou, la définition de session.gc_maxlifetime à partir de votre script PHP ne fonctionnera pas car Plesk a son propre script de ramasse-miettes exécuté à partir de cron.

J'ai utilisé la solution publiée sur le lien ci-dessous pour déplacer le travail cron d'une heure à une autre pour éviter ce problème, alors la réponse ci-dessus devrait fonctionner:

mv /etc/cron.hourly/plesk-php-cleanuper /etc/cron.daily/

https://websavers.ca/plesk-php-sessions-timing-earlier-expected

Neil Walden
la source
3

Mettez $_SESSION['login_time'] = time();dans la page d'authentification précédente. Et l'extrait ci-dessous dans chaque autre page où vous souhaitez vérifier le délai d'expiration de la session.

if(time() - $_SESSION['login_time'] >= 1800){
    session_destroy(); // destroy session.
    header("Location: logout.php");
    die(); // See https://thedailywtf.com/articles/WellIntentioned-Destruction
    //redirect if the page is inactive for 30 minutes
}
else {        
   $_SESSION['login_time'] = time();
   // update 'login_time' to the last time a page containing this code was accessed.
}

Modifier: cela ne fonctionne que si vous avez déjà utilisé les ajustements dans d'autres articles ou désactivé le nettoyage de la mémoire et que vous souhaitez vérifier manuellement la durée de la session. N'oubliez pas d'ajouter die()après une redirection, car certains scripts / robots peuvent l'ignorer. De plus, détruire directement la session avec session_destroy()au lieu de compter sur une redirection pour cela pourrait être une meilleure option, encore une fois, dans le cas d'un client malveillant ou d'un robot.

mohamadRezaSamadi
la source
2

Juste un avis pour un hébergement de partage serveur d' ou ajouté sur les domaines =

Pour que vos paramètres fonctionnent, vous devez avoir un répertoire de session de sauvegarde différent pour le domaine ajouté en utilisant php_value session.save_path "folderA / sessionsA".

Créez donc un dossier sur votre serveur racine, pas dans le public_html et pour ne pas avoir accès à la publicité de l'extérieur. Pour mon cpanel / serveur a bien fonctionné les autorisations de dossier 0700. Essayez ...

  • code php =

     #Session timeout, 2628000 sec = 1 month, 604800 = 1 week, 57600 = 16 hours, 86400 = 1 day
     ini_set('session.save_path', '/home/server/.folderA_sessionsA');
     ini_set('session.gc_maxlifetime', 57600); 
     ini_set('session.cookie_lifetime', 57600);
     ini_set('session.cache_expire', 57600);
     ini_set('session.name', 'MyDomainA');

avant session_start ();

ou

  • .htaccess =

     php_value session.save_path /home/server/.folderA_sessionsA
     php_value session.gc_maxlifetime 57600
     php_value session.cookie_lifetime 57600
     php_value session.cache_expire 57600
     php_value session.name MyDomainA

Après de nombreuses recherches et tests, cela a bien fonctionné pour le serveur cpanel / php7 partagé. Un grand merci à: NoiS

ChriStef
la source
1

Non. Si vous n'avez pas accès au php.ini, vous ne pouvez pas garantir que les changements auront un effet.

Je doute que vous ayez besoin de prolonger la durée de vos sessions.
Il a un délai d'attente assez raisonnable pour le moment et il n'y a aucune raison de le prolonger.

Votre bon sens
la source
Salut Col, j'ai cherché partout dans cet endroit pour trouver un moyen de vous contacter. J'ai vu que vous m'aviez fait des suggestions sur mon dernier message qui était fermé (dimanche.) Je me suis occupé d'un autre projet et maintenant il est parti. J'aimerais vraiment essayer vos suggestions. Est-ce là de toute façon pour trouver ce que vous avez écrit?
Le vieux chien
Pour autant que je puisse voir, il a été non seulement fermé, mais également supprimé. Ces gens n'ont aucun honneur. Oui, votre problème a une solution commune dont je parlais. Je t'écrirai par e-mail. En bref, il s'agissait d'exécuter 2 requêtes supplémentaires pour obtenir ces valeurs précédente / suivante. SELECT id FROM gallery WHERE SortOrder > $currentsortorder LIMIT 1
Votre bon sens
0

Vous pouvez remplacer les valeurs dans php.ini à partir de votre code PHP en utilisant ini_set().

Nathan Q
la source
4
-1: session.gc_maxlifetimen'est pas le paramètre qui contrôle la durée de vie de la session. Il peut être matraqué au travail comme si vous définissez session.gc_divisorà 1, mais c'est tout simplement horrible.
Jon
1
@Jon J'ai vu tellement de réponses sur SO suggérant le contraire, pourquoi? stackoverflow.com/questions/514155/… stackoverflow.com/questions/9904105/…
giannis christofakis
2
@yannishristofakis: gc_maxlifetimedéfinit l'intervalle après lequel les données de session sont éligibles pour le ramasse-miettes - si GC se produit après que ce laps de temps se soit écoulé, les données de session seront détruites (avec les paramètres par défaut, cela équivaut à l'expiration de la session). Mais GC est déclenché de manière probabiliste à chaque démarrage de session, il n'y a donc aucune garantie que la session expirera réellement - vous pouvez tracer une courbe de probabilité en fonction du temps, mais cela ne ressemblera pas à un mur de briques. Ce n'est que la pointe de l'iceberg; voir stackoverflow.com/questions/520237/…
Jon