PHP’s Garbage Collection – Automatisierte Mülltrennung

Sessions und deren Bereinigung unter PHP

Besitzt man eine gut frequentierte Website, stellt sich nicht mehr die Frage OB sondern WIE man sich der Speicherbereinigung bedient. Für Nutzer des Session-Hanlders files bietet PHP eine recht simple Methode um den “Müll” von aktuellen Daten zu trennen. Die s. g. “Garbage Collection” wird mittels eines einfachen Wahrscheinlichkeits-Algorithmus in definierten Abständen aufgerufen und schafft so automatisiert Platz im Speicher.

Diese Parameter sind für eine sinnvolle Konfiguration zu beachten:

session.save_handler = files // Methode der Sessionspeicherung
session.gc_maxlifetime = 1440 // Verfallszeit der Session
session.gc_probability = 1 // Divident
session.gc_divisor = 100 // Divisor

Die oben definierten Einstellungen veranlassen PHP, die serverseitigen Sitzungsvariablen unter dem in session.save_path angegebenen Pfad in Dateien abzulegen sowie den Garbage Collector mit einer 1%tigen Wahrscheinlichkeit aufzurufen. Dieses Verhalten errechnet sich aus gc_brobability/gc_divisor und ergäbe hier den Effekt, dass ca. aller 100 Anfragen eine Speicherbereinigung stattfindet. Da jeder Durchlauf der Funktion nicht gerade ressourcenschonend ist, sollte hierbei viel Wert auf eine sinnvolle Einstellung gelegt werden, um das System nicht unverhältnismäßig zu belasten. Maßgebend sind sowohl die Anzahl der stattfindenen Site-Aufrufe als auch die Verfallszeit der Session an sich.

Es sei abschließend erwähnt, dass eigene Implementierungen einer Session-Verwaltung ein Überschreiben der standardmäßigen in C programmierten Funktion zulassen. Weitere Möglichkeiten wäre der mm-Handler oder eine SQL-Varianten. Die Einstellung session.gc_probability = 0 schaltet die interne Garbage Collection gänzlich ab und lässt somit einer asynchronen Implementierung eigener Funktionen und Jobs den Vorrang.

<?php echo self::$_nachgeschoben; ?>

Was ist eine Session und wofür ist sie gut?

Benutzerinteraktionen zwischen Browser und Webserver finden über das zustandslose HTTP (Hypertext Transfer Protocol) statt. Nach jeder abgeschlossenen Anfrage eines Browsers an den Webserver, wird die vorher aufgebaute Verbindung zwischen Server und Client geschlossen. Ergo weiß der Webserver bei der nächsten Anfrage nicht mehr, ob der betreffende Besucher das erste Mal oder bereits seit einigen Stunden die Website besucht.

Um nun persönliche Nutzerdaten persistent über die Übertragungszeit hinaus – praktisch für eine ganze Sitzung (Session) – dem richtigen Browser und damit dem richtigen Nutzer zuordnen zu können, müssen die Daten auf dem Webserver mit einer eindeutigen Benutzer-ID verbunden werden und diese dem Browser und umgekeht auch dem Server mitgeteilt werden. Der Browser muss diese – bei Sitzungsbeginn generierte – Session-ID mit jeder HTTP-Anfrage übertragen. Damit lässt sich ein Nutzer eindeutig über längere Zeit identifizieren.

Um eine Session unter PHP zu starten reicht folgender Befehl.

session_start();

Wie wird die Session-ID übertragen?

Hierzu gibt es zwei Ansätze. Etabliert und sicherheitstechnisch vorzuziehen ist die “versteckte” Speicherung der Session-ID in einem clientsetigen Sitzungs-Cookie. Dieses wird je nach Gültigkeit im Hauptspeicherbereich des Browsers oder auf der Festplatte des Nutzers hinterlegt und mit jeder Anfrage vom Browser zum Server übertragen.

Eine weitere Möglichkeit ist, die Session-ID sogenannt “transparent” innerhalb der URL, praktisch im $_GET- bzw. $_POST-Request zu übermitteln. Hierbei wird der entsprechende Parameter völlig automatisiert an jeden Link der aktuellen Domain angehangen. Analog dazu funktioniert mittels $_POST-Request eine Übergabe innerhalb der Formulardaten.

Aus http://www.example.com/demo.php wird dabei einfach http://www.example.com/demo.php?PHPSESSID=68ac906495480a...

Anzumerken wäre hier die wesentlich einfachere Möglichkeit des (wenn auch ungewollten) “Session Hijacking”, eine Session durch die Übermittlung an Dritte weiterzugeben. Das geschieht bspw. durch den Versand einer Shop-URL, um einem Freund über einen Sonderpreis zu informieren. Nach einem Login am entsprechenden Shop-System wird nun die URL mitsamt der aktuellen Session-ID per z. B. IM weitergegeben. Mit etwas Glück (und einer mangelhaft serverseitigen Implementierung der Sessionverwaltung) surft nun Ihr Freund mit Ihrer persönlichen Sitzung und kann somit Ihren Einkauf fortsetzen.

Folgende Einstellungen der php.ini sind hierbei erwähnenswert:

session.use_cookies = 1 // Session-ID in Cookies seichern
session.use_only_cookies = 1 // verbietet Sess-IDs in der URL
session.cookie_secure = 1 // Cookies NUR für SSL-Verbindungen
session.cookie_lifetime = 0 // Gültigkeit des Cookie in s; 0 = bis Browser geschlossen wird
session.cookie_httponly = 1 // Kein Zugriff seitens Javascript

Client- oder serverseitige Sessionvariablen?

Diese Frage stellt sich bei der Entwicklung von Websites immer wieder. Was soll im Cookie und was in der Server-Session gespeichert werden? Im Wesentlichen wäre zu beachten, dass Daten, welche auch über eine Sitzung hinaus noch verfügbar sein sollen (bspw. um einen Nutzer beim nächsten Einkauf wieder zu erkennen oder den Warenkorb zu speichern) sinnvollerweise in einem langzeitgültigem Cookie direkt beim Nutzer richtig aufgehoben sind. Jedoch gilt hier meines Erachtens eine maximale Datenmenge von ca. 1KB, da so die meisten Anfragen innerhalb eines Netzwerkpaketes versand werden können und ohne Fragmentierung über mehrere Knotenpunkte beim Server ankommen. Damit optimiert man nicht nur die Latenz sondern spart auch Strom für die Übertragung. Sicherheitshalber sollten die Daten in jedem Fall für Dritte erschwert interpretierbar sein und somit verschlüsselt im Cookie abgelegt werden.

Sensible nutzerspeziefische Daten, insbesondere die des aktuellen Logins, sollten vorzugsweise innerhalb der Server-Session ihr “Zu Hause” haben. Besonders Daten, welche nach dem Sessionende nicht mehr benötigt werden oder ohnehin verfallen sind, können so ohne Weiteres “entsorgt” werden.