web-dev-qa-db-fra.com

Comment changer le délai de session en PHP?

Je voudrais prolonger le délai de 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?

139
Oli

Le délai de session est une notion qui doit être implémentée dans le code si vous souhaitez des garanties strictes. c'est la seule façon vous pouvez être absolument certain qu'aucune session ne survivra après X minutes d'inactivité.

Si assouplir un peu cette exigence est acceptable et que vous pouvez placer un borne inférieure au lieu d'une limite stricte de 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 qui est probablement le cas), 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, définissez session.gc_maxlifetime avec session_set_cookie_params devrait fonctionner pour vous de la manière suivante:

_// 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 qu'il conserve 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 le même laps de temps. 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. En effet, les sessions dont la durée de vie a expiré côté serveur ne sont pas immédiatement récupérées, mais uniquement à chaque fois que le GC de la session démarre .

    Le GC étant un processus potentiellement coûteux, la probabilité est généralement faible, voire nulle (un site Web enregistrant un nombre important de visites renoncera probablement au GC probabiliste et le planifiera 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 pour une durée de vie de session effective sera _session.gc_maxlifetime_, mais la limite supérieure sera imprévisible.

  • Si vous ne définissez pas _session.gc_maxlifetime_ sur la même période, le serveur peut supprimer les données de session inactives antérieures à cette date; dans ce cas, un client qui se souvient toujours de son identifiant de session le présentera mais le serveur ne trouvera aucune donnée associée à cette session, se comportant ainsi 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 un borne supérieure sur l'inactivité de session; ainsi que la limite inférieure vue du dessus, le réglage est 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'ici, nous ne nous sommes pas du tout intéressés aux valeurs exactes de chaque identifiant de session, mais seulement à l'exigence selon laquelle les données doivent exister aussi longtemps que nous en avons besoin. Sachez que dans le cas (peu probable) où les identifiants de session vous importent, vous devez prendre soin de les régénérer avec _session_regenerate_id_ si nécessaire.

298
Jon

Si vous utilisez la gestion de session par défaut de PHP, le seul moyen de changer de manière fiable la durée de la session sur toutes les plateformes est de changer php.ini. En effet, sur certaines plates-formes, la récupération de place est mise en œuvre via un script qui s'exécute à un moment donné (un script cron) qui lit directement à partir de php.ini, et donc toutes les tentatives de le changer au moment de l'exécution, par exemple via ini_set(), ne sont pas fiables et ne fonctionneront probablement pas.

Par exemple, dans les systèmes Linux Debian, la récupération de place interne de PHP est désactivée en définissant session.gc_probability=0 par défaut dans la configuration. Cette opération s'effectue via /etc/cron.d/php, qui s'exécute à XX: 09 et XX: 39 (c'est-à-dire toutes les demi-heures). Ce travail cron recherche les sessions plus anciennes que session.gc_maxlifetime spécifiées 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: le délai de traitement des sessions PHP est trop rapide , le PO rencontrait des problèmes sur un hôte, mais ces problèmes cessaient lors du passage à un autre hôte.

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 souhaitez une solution fiable même si vous changez d’hôte, vous devez utiliser une alternative différente.

Les méthodes alternatives disponibles incluent:

  1. Définissez un autre gestionnaire de session (enregistrer) dans PHP pour enregistrer vos sessions dans un répertoire différent ou dans une base de données, comme indiqué dans PHP: Custom Session Handlers (Manuel de PHP) , donc que le travail cron ne l'atteint pas et que seul le ramassage des ordures interne à PHP a lieu. Cette option peut probablement utiliser ini_set() pour définir session.gc_maxlifetime mais je préfère ignorer simplement maxlifetime paramètre dans mon gc() callback et déterminer seul la durée de vie maximale.

  2. Oubliez complètement la gestion de session interne par 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, de sorte que vous perdez l'avantage du super-global $_SESSION et qu'il a besoin de plus de code, ce qui offre davantage de possibilités de bogues et de 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 par cryptographie pour éviter la prédictibilité de l'identifiant de session (entraînant un éventuel détournement de session), ce qui n'est pas si facile à faire avec PHP portablement. Le principal avantage est que cela fonctionnera de manière cohérente sur toutes les plates-formes et que vous aurez le plein contrôle du code. C'est l'approche adoptée par exemple. par le logiciel de forum phpBB (au moins la version 1; je ne suis pas sûr des versions plus récentes).

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

<?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 vous-même toutes les fonctions de session. Je ne vais pas entrer dans les détails ici.

30
Pedro Gimeno

Ajouter un commentaire à ceux qui utilisent Plesk et qui rencontrent des problèmes avec tout ce qui est mentionné ci-dessus me rendait dingue. Définir session.gc_maxlifetime à partir de votre script PHP ne fonctionnera pas, car Plesk a son propre script de récupération de place exécuté à partir de cron.

Pour résoudre ce problème, j’ai utilisé la solution affichée sur le lien ci-dessous, qui consiste à déplacer le travail cron d’horaire en heure, puis 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

3
Neil Walden

Placez $_SESSION['login_time'] = time(); dans la page d'authentification précédente. Et la capture 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.
}

Edit: Cela ne fonctionne que si vous avez déjà utilisé les réglages dans d'autres messages ou si vous avez désactivé Garbage Collection et si 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. En outre, détruire directement la session avec session_destroy() au lieu de compter sur une redirection pourrait être une meilleure option, encore une fois, dans le cas d’un client malveillant ou d’un robot.

3
mohamadRezaSamadi

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

Je doute que vous ayez besoin de prolonger vos sessions.
Le délai d’attente est assez raisonnable pour le moment et il n’ya aucune raison de le prolonger.

1
Your Common Sense

Vous pouvez remplacer les valeurs du fichier php.ini à partir de votre code PHP à l'aide de ini_set().

0
Nathan Q