web-dev-qa-db-ger.com

Wie ändere ich das Sitzungs-Timeout in PHP?

Ich möchte das Session-Timeout in PHP verlängern

Ich weiß, dass dies durch Ändern der Datei php.ini möglich ist. Aber ich habe keinen Zugang dazu.

Kann man das also nur mit PHP-Code machen?

139
Oli

Session Timeout ist ein Begriff, der in Code implementiert werden muss, wenn Sie strenge Garantien wünschen. das ist der einzige Weg Sie können absolut sicher sein, dass keine Sitzung nach X Minuten Inaktivität jemals überleben wird.

Wenn es akzeptabel ist, diese Anforderung ein wenig zu lockern und Sie in Ordnung sind, ein ntergrenze anstelle einer strengen Begrenzung der Dauer zu setzen, können Sie dies einfach und ohne das Schreiben einer benutzerdefinierten Logik tun.

Bequemlichkeit in entspannter Umgebung: wie und warum

Wenn Ihre Sitzungen mit Cookies implementiert sind (was sie wahrscheinlich sind), und wenn Die Clients sind nicht böswillig. Sie können eine Obergrenze für die Sitzungsdauer festlegen, indem Sie bestimmte Parameter anpassen. Wenn Sie die Standard-Session-Behandlung von PHP mit Cookies verwenden, setzen Sie session.gc_maxlifetime zusammen mit session_set_cookie_params sollte für dich so funktionieren:

// 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!

Dies funktioniert, indem der Server so konfiguriert wird, dass die Sitzungsdaten mindestens eine Stunde lang inaktiv bleiben, und Ihre Clients angewiesen werden, ihre Sitzungs-ID nach derselben Zeitspanne zu "vergessen". Beide Schritte sind erforderlich, um das erwartete Ergebnis zu erzielen.

  • Wenn Sie den Clients nicht anweisen, ihre Sitzungs-ID nach einer Stunde zu vergessen (oder wenn die Clients böswillig sind und Ihre Anweisungen ignorieren), verwenden sie weiterhin dieselbe Sitzungs-ID und ihre effektive Dauer ist nicht deterministisch. Dies liegt daran, dass Sitzungen, deren Lebensdauer auf der Serverseite abgelaufen ist, nicht sofort mit Datenmüll gesammelt werden, sondern nur dann , wenn der Sitzungs-GC einschaltet .

    GC ist ein potenziell teurer Prozess, daher ist die Wahrscheinlichkeit in der Regel eher gering oder sogar null (eine Website, die eine große Anzahl von Treffern erzielt, verzichtet wahrscheinlich vollständig auf probabilistische GC und plant sie alle X Minuten im Hintergrund). In beiden Fällen (bei nicht kooperierenden Clients) beträgt die Untergrenze für die effektive Sitzungslebensdauer session.gc_maxlifetime, Die Obergrenze ist jedoch unvorhersehbar.

  • Wenn Sie session.gc_maxlifetime Nicht auf die gleiche Zeitspanne einstellen, verwirft der Server möglicherweise Sitzungsdaten, die sich im Leerlauf befinden. In diesem Fall zeigt ein Client, der sich noch an seine Sitzungs-ID erinnert, diese an, der Server findet jedoch keine dieser Sitzung zugeordneten Daten und verhält sich so, als ob die Sitzung gerade gestartet worden wäre.

Sicherheit in kritischen Umgebungen

Sie können die Dinge vollständig steuerbar machen, indem Sie eine benutzerdefinierte Logik verwenden, um auch eine obere Schranke für Sitzungsinaktivität zu setzen. zusammen mit der Untergrenze von oben ergibt dies eine strenge Einstellung.

Speichern Sie dazu die obere Grenze zusammen mit den restlichen Sitzungsdaten:

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;

Sitzungs-ID-Persistenz

Bisher haben wir uns überhaupt nicht mit den genauen Werten jeder Sitzungs-ID befasst, sondern nur mit der Anforderung, dass die Daten so lange existieren sollten, wie wir sie benötigen. Beachten Sie, dass in dem (unwahrscheinlichen) Fall, dass Ihnen Sitzungs-IDs wichtig sind, darauf geachtet werden muss, diese bei Bedarf mit session_regenerate_id Neu zu generieren.

298
Jon

Wenn Sie die standardmäßige Sitzungsbehandlung von PHP verwenden, können Sie die Sitzungsdauer auf allen Plattformen nur zuverlässig ändern, indem Sie php.ini ändern. Dies liegt daran, dass auf einigen Plattformen die Speicherbereinigung über ein Skript implementiert wird, das zu jeder bestimmten Zeit ausgeführt wird (ein cron Skript), das direkt aus php.ini und liest daher alle Versuche, es zur Laufzeit zu ändern, z via ini_set() sind unzuverlässig und funktionieren höchstwahrscheinlich nicht.

Beispielsweise wird in Debian Linux-Systemen die interne Garbage Collection von PHP deaktiviert, indem standardmäßig session.gc_probability=0 In der Konfiguration festgelegt wird. Dies geschieht stattdessen über /etc/cron.d/php, das unter XX: 09 und XX ausgeführt wird : 39 (dh jede halbe Stunde). Dieser Cron-Job sucht nach Sitzungen, die älter als die in der Konfiguration angegebene session.gc_maxlifetime sind, und wenn welche gefunden werden, werden diese gelöscht. Infolgedessen wird in diesen Systemen ini_set('session.gc_maxlifetime', ...) ignoriert. Das erklärt auch, warum in dieser Frage: PHP-Sitzungen laufen zu schnell ab , das OP hatte Probleme auf einem Host, aber die Probleme hörten auf, wenn auf einen anderen Host gewechselt wurde.

Da Sie also keinen Zugriff auf php.ini haben, ist die Verwendung der standardmäßigen Sitzungsbehandlung keine Option, wenn Sie dies portabel tun möchten. Anscheinend hat es Ihrem Host gereicht, die Lebensdauer der Cookies zu verlängern. Wenn Sie jedoch eine Lösung suchen, die auch bei einem Hostwechsel zuverlässig funktioniert, müssen Sie eine andere Alternative wählen.

Zu den verfügbaren alternativen Methoden gehören:

  1. Setzen Sie einen anderen Session (Save) Handler in PHP, um Ihre Sessions in einem anderen Verzeichnis oder in einer Datenbank zu speichern, wie in PHP: Custom Session Handlers (PHP manual) angegeben dass der cron Job es nicht erreicht und nur die interne Garbage Collection von PHP stattfindet. Diese Option kann wahrscheinlich ini_set() verwenden, um session.gc_maxlifetime festzulegen, aber ich ziehe es vor, die maxlifetime einfach zu ignorieren Parameter in meinem gc() Rückruf und bestimmen selbst die maximale Lebensdauer.

  2. Vergessen Sie die PHP interne Sitzungsverwaltung vollständig und implementieren Sie Ihre eigene Sitzungsverwaltung. Diese Methode hat zwei Hauptnachteile: Sie benötigen Ihre eigenen globalen Sitzungsvariablen, so dass Sie den Vorteil des $_SESSION - Superglobals verlieren und mehr Code benötigen, wodurch mehr Möglichkeiten für Fehler und Sicherheitslücken bestehen. Am wichtigsten ist, dass die Sitzungskennung aus kryptografisch sicheren Zufalls- oder Pseudozufallszahlen generiert wird, um die Vorhersehbarkeit der Sitzungs-ID zu vermeiden (was zu möglicher Sitzungsentführung führen kann). Dies ist nicht so einfach mit PHP portabel. Der Hauptvorteil ist, dass es auf allen Plattformen konsistent funktioniert und Sie die volle Kontrolle über den Code haben. Das ist der Ansatz, der z. von der phpBB Forensoftware (mindestens Version 1; bei neueren Versionen bin ich mir nicht sicher).

Es gibt ein Beispiel für (1) in der Dokumentation für session_set_save_handler() . Das Beispiel ist lang, aber ich werde es hier wiedergeben, mit den relevanten Änderungen, die zur Verlängerung der Sitzungsdauer erforderlich sind. Beachten Sie die Einbeziehung von session_set_cookie_params(), um die Lebensdauer der Cookies zu verlängern.

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

Ansatz (2) ist komplizierter; Grundsätzlich müssen Sie alle Sitzungsfunktionen selbst neu implementieren. Ich werde hier nicht auf Details eingehen.

30
Pedro Gimeno

Das Hinzufügen eines Kommentars für jeden, der Plesk verwendet, der Probleme mit den oben genannten hat, da es mich in den Wahnsinn getrieben hat, und das Festlegen von session.gc_maxlifetime in Ihrem PHP= Skript funktioniert nicht, da Plesk ein eigenes Garbage Collection-Skript hat, das von cron ausgeführt wird .

Ich habe die unter dem folgenden Link angegebene Lösung verwendet, um den Cron-Job von stündlich auf täglich zu verschieben, um dieses Problem zu vermeiden. Die Antwort oben sollte dann funktionieren:

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

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

3
Neil Walden

Fügen Sie $_SESSION['login_time'] = time(); in die vorherige Authentifizierungsseite ein. Und das unten auf jeder anderen Seite, auf der Sie das Sitzungs-Timeout überprüfen möchten.

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: Dies funktioniert nur, wenn Sie die Tweaks bereits in anderen Posts verwendet oder die Garbage Collection deaktiviert haben und die Sitzungsdauer manuell überprüfen möchten. Vergessen Sie nicht, die() nach einer Umleitung hinzuzufügen, da einige Skripte/Robots dies möglicherweise ignorieren. Im Falle eines böswilligen Clients oder eines Roboters ist es möglicherweise auch besser, die Sitzung direkt mit session_destroy() zu zerstören, anstatt sich auf eine Umleitung zu verlassen.

3

Nein. Wenn Sie keinen Zugriff auf die php.ini haben, können Sie nicht garantieren, dass Änderungen Auswirkungen haben.

Ich bezweifle, dass Sie Ihre Sitzungszeit verlängern müssen.
Momentan hat es ein ziemlich vernünftiges Timeout und es gibt keinen Grund, es zu verlängern.

1

Sie können Werte in der php.ini aus Ihrem PHP Code mit ini_set() überschreiben.

0
Nathan Q