Wie ändere ich das Sitzungszeitlimit in PHP?

Antworten:

324

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

Wenn es akzeptabel ist, diese Anforderung ein wenig zu lockern, und Sie eine Untergrenze anstelle einer strengen Begrenzung der Dauer festlegen können, können Sie dies einfach und ohne benutzerdefinierte Logik tun.

Komfort in entspannten Umgebungen: wie und warum

Wenn Sie Ihre Sitzungen mit Cookies implementiert sind (was sie wahrscheinlich sind), und wenn die Kunden nicht bösartig sind, können Sie eine obere auf der Sitzungsdauer gebunden gesetzt durch bestimmte Parameter zwicken. Wenn Sie die Standard-Sitzungsbehandlung von PHP mit Cookies verwenden, sollte die Einstellung session.gc_maxlifetimezusammen mit session_set_cookie_paramsfür Sie wie folgt 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 sagen, dass sie ihre Sitzungs-ID nach einer Stunde vergessen sollen (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 Müll gesammelt werden, sondern nur dann, wenn der Sitzungs-GC startet .

    GC ist ein potenziell teurer Prozess, daher ist die Wahrscheinlichkeit in der Regel eher gering oder sogar gleich Null (eine Website mit einer großen Anzahl von Treffern verzichtet wahrscheinlich vollständig auf probabilistische GC und plant dies alle X Minuten im Hintergrund). In beiden Fällen (unter der Annahme nicht kooperierender Clients) ist die Untergrenze für effektive Sitzungslebensdauern session.gc_maxlifetime, die Obergrenze jedoch unvorhersehbar.

  • Wenn Sie nicht session.gc_maxlifetimedieselbe Zeitspanne festlegen , verwirft der Server möglicherweise früher inaktive Sitzungsdaten. In diesem Fall wird sie von einem Client angezeigt, der sich noch an seine Sitzungs-ID erinnert. Der Server findet jedoch keine mit dieser Sitzung verknüpften 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 benutzerdefinierte Logik verwenden, um auch eine Obergrenze für die Inaktivität von Sitzungen festzulegen. zusammen mit der Untergrenze von oben ergibt sich eine strenge Einstellung.

Speichern Sie dazu die Obergrenze 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;

Persistenz der Sitzungs-ID

Bisher haben wir uns überhaupt nicht mit den genauen Werten jeder Sitzungs-ID befasst, sondern nur mit der Anforderung, dass die Daten so lange vorhanden sein müssen, wie wir sie benötigen. Beachten Sie, dass in dem (unwahrscheinlichen) Fall, dass Sitzungs-IDs für Sie von Bedeutung sind, darauf geachtet werden muss, diese session_regenerate_idbei Bedarf neu zu generieren .

Jon
quelle
Frage: Wenn Sie dies nennen, sagen wir einfach jede Minute, wird es sein Limit erhöhen? Beispiel um 10:00 Ich habe es so genannt, dass sein Limit 11:00 ist. Nach 1 Minute, 10:01, wird das Limit 11:01 sein?
Oneofakind
@oneofakind: Wenn du was genau anrufst?
Jon
1
Diese: ini_set ('session.gc_maxlifetime', 3600); session_set_cookie_params (3600);
Oneofakind
@oneofakind: Ja, aber nur , wenn Sie rufen session_start()auch (sonst keine Wirkung überhaupt) und nur , wenn Sie immer die beide vor anrufen session_start(sonst gc_maxlifetimehat das Potenzial , um alle Sitzungen zu beeinflussen derzeit offen, während session_set_cookie_paramsnur eine neue Sitzung beeinflussen kann , dass beginnt mit die aktuelle Anfrage).
Jon
@Jon Wenn ich session_start () erneut aufrufe, wird dann alles in meiner $ _SESSION zurückgesetzt? Wenn Sie mit "hat das Potenzial, alle Sitzungen zu beeinflussen" meinen, wie? Danke für die Antwort.
Oneofakind
33

Wenn Sie die Standard-Sitzungsbehandlung von PHP verwenden, können Sie die Sitzungsdauer auf allen Plattformen nur zuverlässig ändern, indem Sie die Datei php.ini ändern . Dies liegt daran, dass auf einigen Plattformen die Speicherbereinigung über ein Skript implementiert wird, das jedes Mal ausgeführt wird (ein Cron- Skript), das direkt aus der php.ini liest. Daher sind alle Versuche, sie zur Laufzeit zu ändern, z. B. über ini_set(), unzuverlässig und höchstwahrscheinlich wird nicht funktionieren.

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

Da Sie keinen Zugriff auf php.ini haben , ist die Verwendung der Standard-Sitzungsbehandlung keine Option, wenn Sie dies portabel tun möchten. Anscheinend hat die Verlängerung der Cookie-Lebensdauer für Ihren Host ausgereicht. Wenn Sie jedoch eine Lösung suchen, die auch dann zuverlässig funktioniert, wenn Sie den Host wechseln, müssen Sie eine andere Alternative verwenden.

Verfügbare alternative Methoden umfassen:

  1. Stellen Sie in PHP einen anderen Sitzungshandler (Speichern) ein, um Ihre Sitzungen in einem anderen Verzeichnis oder in einer Datenbank zu speichern, wie in PHP: Benutzerdefinierte Sitzungshandler (PHP-Handbuch) angegeben , damit der Cron- Job ihn nicht erreicht, und nur PHPs Die interne Speicherbereinigung findet statt. Diese Option kann wahrscheinlich verwendet werden ini_set(), um session.gc_maxlifetime festzulegen, aber ich bevorzuge es, den Parameter maxlifetime in meinem gc()Rückruf einfach zu ignorieren und die maximale Lebensdauer selbst zu bestimmen.

  2. Vergessen Sie die interne PHP-Sitzungsverwaltung vollständig und implementieren Sie Ihre eigene Sitzungsverwaltung. Diese Methode hat zwei Hauptnachteile: Sie benötigen Ihre eigenen globalen Sitzungsvariablen, sodass Sie den Vorteil der $_SESSIONSuperglobalität verlieren , und sie benötigt mehr Code, sodass 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 eine Vorhersagbarkeit der Sitzungs-ID zu vermeiden (was zu einer möglichen Entführung von Sitzungen führt), und dies ist mit PHP nicht so einfach portabel. Der Hauptvorteil ist, dass es auf allen Plattformen konsistent funktioniert und Sie die volle Kontrolle über den Code haben. Dies ist der Ansatz, der beispielsweise von der phpBB- Forensoftware verfolgt wird (mindestens Version 1; ich bin mir bei neueren Versionen nicht sicher).

Es gibt ein Beispiel für (1) in der Dokumentation fürsession_set_save_handler() . Das Beispiel ist lang, aber ich werde es hier mit den relevanten Änderungen reproduzieren, die zur Verlängerung der Sitzungsdauer erforderlich sind. Beachten Sie die Aufnahme von session_set_cookie_params(), um auch 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.

Pedro Gimeno
quelle
Könnte jemand das bestätigen?
Oli
@Oli: Es sieht nach einem flüchtigen Lesen richtig aus. Vielleicht möchten Sie sich auch stackoverflow.com/questions/520237/… ansehen , aber wenn Sie keinen Zugriff auf php.iniIhre praktischen Optionen haben, sind diese stark eingeschränkt.
Jon
Unter Ubuntu 14 /usr/lib/php5/maxlifetimewird anscheinend kein Wert unter 24 Minuten berechnet. Sie können Ihre Sitzungszeitlimits also nicht niedriger einstellen.
Henry
"Vergessen Sie die interne PHP-Sitzungsverwaltung vollständig und implementieren Sie Ihre eigene Sitzungsverwaltung." Guter Gott, das ist ein gefährlicher Rat. Ein Sicherheitsalptraum würde sich zwangsläufig ergeben.
Kzqai
@ Kzqai Ich stelle auch fest, dass "es mehr Code benötigt, daher gibt es mehr Möglichkeiten für Fehler und Sicherheitslücken". Es ist kein Rat, ich zähle die Alternativen auf, aber wenn Sie einen Vorschlag zur Verbesserung haben, tun Sie dies bitte.
Pedro Gimeno
3

Das Hinzufügen eines Kommentars für alle Benutzer von Plesk, die Probleme mit einem der oben genannten Probleme haben, da es mich verrückt gemacht hat. 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. Dann sollte die obige Antwort funktionieren:

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

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

Neil Walden
quelle
3

Setzen Sie $_SESSION['login_time'] = time();in die vorherige Authentifizierung Seite. Und das unten auf jeder anderen Seite, auf der Sie das Sitzungszeitlimit ü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.
}

Bearbeiten: Dies funktioniert nur, wenn Sie die Optimierungen 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 / Roboter dies möglicherweise ignorieren. session_destroy()Im Falle eines böswilligen Clients oder eines Roboters ist es möglicherweise auch besser , die Sitzung direkt zu zerstören, anstatt sich auf eine Umleitung zu verlassen.

mohamadRezaSamadi
quelle
2

Nur ein Hinweis für einen gemeinsam genutzten Hosting- Server oder für Domains hinzugefügt =

Damit Ihre Einstellungen funktionieren, müssen Sie ein anderes Sitzungsverzeichnis für die hinzugefügte Domäne verwenden, indem Sie php_value session.save_path "folderA / sessionA" verwenden.

Erstellen Sie also einen Ordner auf Ihrem Stammserver, nicht in public_html und nicht für den Zugriff auf Werbung von außen. Für mein cpanel / Server funktionierten die Ordnerberechtigungen 0700 einwandfrei. Probieren Sie es aus ...

  • PHP-Code =

     #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');

vor session_start ();

oder

  • .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

Nach vielen Recherchen und Tests funktionierte dies einwandfrei für gemeinsam genutzte cpanel / php7-Server. Vielen Dank an: NoiS

ChriStef
quelle
1

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.
Es hat im Moment eine ziemlich vernünftige Zeitüberschreitung und es gibt keine Gründe, sie zu verlängern.

Ihr gesunder Menschenverstand
quelle
Hallo Col, ich habe überall gesucht, um einen Weg zu finden, dich zu kontaktieren. Ich habe gesehen, dass Sie mir einige Vorschläge für meinen letzten Beitrag gegeben haben, der geschlossen war (Sonntag). Ich war mit einem anderen Projekt beschäftigt und jetzt ist es weg. Ich würde gerne Ihre Vorschläge ausprobieren. Ist das sowieso da, um herauszufinden, was du geschrieben hast?
Der alte Hund
Soweit ich sehen kann, wurde es nicht nur geschlossen, sondern auch gelöscht. Diese Leute haben keine Ehre. Ja, Ihr Problem hat eine gemeinsame Lösung, über die ich gesprochen habe. Ich schreibe dir per E-Mail. Kurz gesagt, es ging darum, zwei zusätzliche Abfragen auszuführen, um diese vorherigen / nächsten Werte zu erhalten. SELECT id FROM gallery WHERE SortOrder > $currentsortorder LIMIT 1
Ihr gesunder Menschenverstand
0

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

Nathan Q.
quelle
4
-1: session.gc_maxlifetimeist nicht die Einstellung, die die Sitzungslebensdauer steuert. Es kann so an der Arbeit geprügelt werden , wenn Sie setzen session.gc_divisorauf 1, aber das ist einfach schrecklich.
Jon
1
@ Jon Ich habe so viele Antworten auf SO gesehen, die das Gegenteil vorschlagen. Warum ist das so? stackoverflow.com/questions/514155/… stackoverflow.com/questions/9904105/…
giannis christofakis
2
@yannishristofakis: Legt gc_maxlifetimedas Intervall fest, nach dem Sitzungsdaten für die Speicherbereinigung berechtigt sind. Wenn die GC nach Ablauf dieser Zeit auftritt, werden die Sitzungsdaten zerstört (mit den Standardeinstellungen entspricht dies dem Ablauf der Sitzung). GC wird jedoch wahrscheinlich bei jedem Sitzungsstart ausgelöst, sodass nicht garantiert werden kann, dass die Sitzung tatsächlich abläuft. Sie können eine Kurve von Prob gegen Zeit zeichnen, sie sieht jedoch nicht wie eine Mauer aus. Das ist nur die Spitze des Eisbergs; siehe stackoverflow.com/questions/520237/…
Jon