Sessions

HTTP ist ein zustandsloses Protokoll; fast jede Anwendung muss jedoch den Zustand zwischen den Requests bewahren, etwa den Inhalt eines Warenkorbs. Genau dafür dienen Sessions. Wir zeigen Ihnen:

  • wie man Sessions verwendet
  • wie man Namenskonflikte vermeidet
  • wie man die Ablaufzeit einstellt

Bei der Verwendung von Sessions erhält jeder Benutzer einen eindeutigen Bezeichner, die Session-ID, die in einem Cookie übertragen wird. Sie dient als Schlüssel zu den Session-Daten. Anders als Cookies, die auf der Seite des Browsers gespeichert werden, liegen die Session-Daten auf der Seite des Servers.

Sessions konfigurieren wir in der Konfiguration; besonders wichtig ist die Wahl der Ablaufzeit.

Um die Verwaltung der Session kümmert sich das Objekt Nette\Http\Session, das Sie sich per Dependency Injection übergeben lassen können. In Presentern genügt der Aufruf $session = $this->getSession().

Installation und Anforderungen

Session starten

Standardmäßig startet Nette die Session automatisch in dem Moment, in dem wir beginnen, Daten aus ihr zu lesen oder in sie zu schreiben. Um eine Session manuell zu starten, verwenden Sie $session->start().

PHP sendet beim Starten der Session HTTP-Header, die das Caching beeinflussen (siehe session_cache_limiter), und eventuell ein Cookie mit der Session-ID. Deshalb muss die Session immer gestartet werden, bevor irgendeine Ausgabe an den Browser gesendet wird; sonst wird eine Exception geworfen. Wenn Sie also wissen, dass beim Rendern der Seite eine Session verwendet wird, starten Sie sie vorher manuell, zum Beispiel im Presenter.

Im Entwicklungsmodus startet Tracy die Session, weil sie sie zur Anzeige der Bars für Weiterleitungen und AJAX-Requests in der Tracy Bar nutzt.

Abschnitte

In reinem PHP ist der Speicher für Session-Daten als Array umgesetzt, das über die globale Variable $_SESSION zugänglich ist. Das Problem ist, dass Anwendungen üblicherweise aus vielen unabhängigen Teilen bestehen, und wenn allen nur ein einziges Array zur Verfügung steht, kommt es früher oder später zu einer Namenskollision.

Das Nette Framework löst dieses Problem, indem es den gesamten Raum in Abschnitte aufteilt (Objekte vom Typ Nette\Http\SessionSection). Jede Einheit nutzt dann ihren eigenen Abschnitt mit einem eindeutigen Namen, und es kann zu keiner Kollision kommen.

Einen Abschnitt erhalten wir von der Session:

$section = $session->getSection('eindeutiger Name');

Im Presenter genügt getSession() mit einem Parameter:

// $this ist ein Presenter
$section = $this->getSession('eindeutiger Name');

Ob ein Abschnitt existiert, lässt sich mit der Methode $session->hasSection('eindeutiger Name') prüfen. Eine Liste der Namen aller existierenden Abschnitte liefert $session->getSectionNames().

Die Arbeit mit dem Abschnitt selbst ist dann mit den Methoden set(), get() und remove() sehr einfach:

// eine Variable schreiben
$section->set('userName', 'john');

// eine Variable lesen, gibt null zurück, wenn sie nicht existiert
echo $section->get('userName');

// eine Variable entfernen
$section->remove('userName');

Um alle Variablen eines Abschnitts zu erhalten, können Sie eine foreach-Schleife verwenden:

foreach ($section as $key => $val) {
	echo "$key = $val";
}

Ablaufzeit einstellen

Die Ablaufzeit lässt sich für einzelne Abschnitte oder sogar für einzelne Variablen einstellen. Wir können die Anmeldung eines Benutzers nach 20 Minuten ablaufen lassen und uns den Inhalt des Warenkorbs trotzdem weiter merken.

// der Abschnitt läuft nach 20 Minuten ab
$section->setExpiration('20 minutes');

Um die Ablaufzeit für einzelne Variablen zu setzen, verwenden Sie den dritten Parameter der Methode set():

// die Variable 'flash' läuft nach 30 Sekunden ab
$section->set('flash', $message, '30 seconds');

Denken Sie daran, dass die Ablaufzeit der gesamten Session (siehe Session-Konfiguration) gleich oder größer sein muss als die für einzelne Abschnitte oder Variablen gesetzte Zeit.

Um eine zuvor gesetzte Ablaufzeit aufzuheben, verwenden Sie die Methode removeExpiration(); um die Ablaufzeit einer bestimmten Variablen zu löschen, übergeben Sie ihren Namen: removeExpiration('flash'). Um den gesamten Abschnitt sofort zu entfernen, verwenden Sie die Methode remove().

Events $onStart, $onBeforeWrite

Das Objekt Nette\Http\Session hat die Events $onStart und $onBeforeWrite, Sie können also Callbacks hinzufügen, die nach dem Start der Session bzw. vor dem Schreiben auf die Festplatte und dem anschließenden Beenden aufgerufen werden.

$session->onBeforeWrite[] = function () {
	// Daten in die Session schreiben
	$this->section->set('basket', $this->basket);
};

Session-Verwaltung

Übersicht der Methoden der Klasse Nette\Http\Session zur Verwaltung der Session:

start(): void

Startet die Session.

isStarted(): bool

Ist die Session gestartet?

close(): void

Beendet die Session. Die Session endet am Ende der Skriptausführung automatisch.

destroy(): void

Beendet und löscht die Session.

exists(): bool

Enthält der HTTP-Request ein Cookie mit einer Session-ID?

regenerateId(): void

Erzeugt eine neue zufällige Session-ID. Die Daten bleiben erhalten.

getId(): string

Gibt die Session-ID zurück.

Konfiguration

Die Session konfigurieren wir in der Konfiguration. Wenn Sie eine Anwendung schreiben, die keinen DI-Container verwendet, nutzen Sie zur Konfiguration diese Methoden. Sie müssen vor dem Start der Session aufgerufen werden.

setName (string $name): static

Setzt den Namen des Cookies, in dem die Session-ID übertragen wird. Der Standardname ist PHPSESSID. Das ist nützlich, wenn Sie mehrere verschiedene Anwendungen auf derselben Website betreiben.

getName(): string

Gibt den Namen des Cookies zurück, in dem die Session-ID übertragen wird.

setOptions (array $options)static

Konfiguriert die Session. Es lassen sich alle Session-Direktiven von PHP setzen (im camelCase-Format, schreiben Sie also z. B. savePath statt session.save_path) und außerdem readAndClose.

setExpiration (?string $expire)static

Setzt die Zeit der Inaktivität, nach der die Session abläuft.

setCookieParameters (string $path, ?string $domain=null, ?bool $secure=null, SameSite|string|null $samesite=null)static

Setzt die Parameter für Cookies. Die Standardwerte der Parameter können Sie in der Konfiguration ändern.

setSavePath (string $path)static

Setzt das Verzeichnis, in dem die Session-Dateien gespeichert werden.

setHandler (\SessionHandlerInterface $handler)static

Setzt einen eigenen Handler, siehe die PHP-Dokumentation.

Sicherheit geht vor

Der Server geht davon aus, dass er mit demselben Benutzer kommuniziert, solange die Requests dieselbe Session-ID mitbringen. Aufgabe der Sicherheitsmechanismen ist es, dafür zu sorgen, dass das auch tatsächlich so ist und der Bezeichner sich weder stehlen noch austauschen lässt.

Das Nette Framework konfiguriert die PHP-Direktiven deshalb richtig, sodass die Session-ID nur in Cookies übertragen wird, für JavaScript unzugänglich ist und Bezeichner in der URL ignoriert werden. Außerdem erzeugt es in kritischen Momenten, etwa bei der Anmeldung eines Benutzers, eine neue Session-ID.

Zur Konfiguration von PHP dient die Funktion ini_set, die manche Hoster leider verbieten. Wenn das bei Ihrem Hoster der Fall ist, versuchen Sie mit ihm zu vereinbaren, dass er Ihnen diese Funktion erlaubt oder den Server wenigstens richtig konfiguriert.

Version: 4.x