Session-basierte Entwicklung mit PHP

Mit PHP in Sitzung
Kommentare

Betrachtet man das WWW einmal aus der Sicht eines Webservers, so ist das Leben wohl ziemlich eintönig: Jeder Dateiabruf stellt ein für sich einzigartiges und zusammenhangloses Ereignis dar. Diesen vermeintlich traurigen Umstand verdankt der Kollege Webserver den Erfindern des Protokolls HTTP, welches – anders als die meisten anderen im Internet gängigen Protokolle – verbindungslos arbeitet und somit jede Anfrage isoliert betrachtet.

Dies mag bei einfachen, zumeist statischen Seiten noch akzeptabel – gar von Vorteil – sein, spätestens wenn benutzerabhängige Daten wie Einstellungen oder Warenkörbe in die Seite integriert werden, braucht die im Hintergrund werkelnde Anwendung jedoch fast immer mehr Informationen: Hat der Besucher bereits Waren ausgewählt? Ist der Benutzer angemeldet? Um nicht ständig alle relevanten Daten händisch von Seite zu Seite mitschleifen zu müssen, könnte man Cookies verwenden. Nun haben diese beim Surfer abgelegten Kekse jedoch einen gravierenden Nachteil: Sie liegen beim Benutzer und entziehen sich damit der Kontrolle der Anwendung. Wenn man auf die Richtigkeit der im Cookie gespeicherten Informationen angewiesen ist, stellt dies ein nicht zu unterschätzendes (Sicherheits-)Problem dar. Zudem kann der Benutzer die Annahme von Cookies verweigern – was dann? Eine Session wird auf dem Server selbst verwaltet und nur die zur Verwaltung notwendige ID wird nach außen preisgegeben. Die hierbei einzig verbleibende Gefahr stellt das Entführen einer Session-ID dar. Wie sich dieses zumindest in Ansätzen verhindern lässt, klären wir später im Praxis-Teil (den notwendigen Quellcode finden Sie auf der Heft-CD sowie in Auszügen auf den nächsten Seiten). Seit der Version 4 sind Session-Funktionen fester Bestandteil des Sprachumfangs von PHP. Wer auf die Verwendung älterer Versionen von PHP angewiesen ist, kann die Session-Funktionen der PHPLib (phplib.sourceforge.net/) zur Hilfe nehmen. Neben der für ältere Versionen notwendigen eigenen Implementation bietet die PHPLib zudem Unterstützung für das Session-System der PHP Version 4 (www.sanisoft.com/phplib/manual/php4_sessions.php). PHP 4 und Apache stellen dem geneigten Entwickler eine Fülle an Möglichkeiten zur Übergabe einer Session-ID, kurz SID, zur Verfügung. Die zwei wohl gängigsten Methoden sind die Speicherung in einem Cookie und die Übergabe als GET- bzw. POST-Parameter (welche von PHP automatisch als Fallback bei ausgeschalteten Cookies verwendet wird). Weitere bekannte Möglichkeiten sind die Verwendung von Wildcard-DNS zur Speicherung der SID im Hostnamen [Wildcard] oder der Einsatz des Apache-Modules mod_rewrite. Eine Sitzung wird in der Regel mit dem Aufruf der ersten Seite gestartet. Dies kann sowohl automatisch ( Einstellung session.autostart=1 in der php.ini) als auch durch den manuellen Aufruf von session_start() erfolgen. PHP durchsucht daraufhin automatisch die COOKIE-, GET- und POST-Variablen nach dem Vorhandensein einer gültigen SID. Falls Sie eine von PHP abweichende Meinung über das Thema Gültigkeit einer SID haben oder Sie eine selbst entwickelte Methode zur Übergabe der SID verwenden, so kann die SID auch händisch durch den Aufruf von session_id($MeineID) vor dem Starten der Sitzung gesetzt oder die Verarbeitung abgebrochen werden. Hat man sich bzw. PHP davon überzeugt, dass es sich um eine gültige Session handelt, stehen die in der Session abgelegten Daten zur Verfügung: Zum einen über das mit PHP 4.1.0 eingeführte superglobale Array $_SESSION, zum anderen über das inzwischen veraltete System-Array $HTTP_SESSION_VARS. Sollte Ihre PHP-Konfiguration aus Kompatiblitätsgründen zudem noch mit register_globals=ON arbeiten, so werden alle in $_SESSION respektive $HTTP_SESSION_VARS gespeicherten Daten in den globalen Variablenscope importiert und stehen somit als normale Variablen zur Verfügung. Doch bevor man Daten aus einer Session erhalten kann, müssen erst einmal auch Daten abgelegt werden. Die optimale Methode zum Ablegen von Daten in einer Session hängt stark von der verwendeten PHP-Version und dem Schalter für register_globals ab.

PHP ab Version 4.1 (mit ausgeschaltetem register_globals)

Nach dem Start einer Session ist das System-Array $_SESSION definiert und kann wie gewohnt bearbeitet werden. Im Gegensatz zu normalen Arrays und sonstigen Variablen ist das $_SESSION-Array superglobal und damit ohne vorgestelltes global in Funktionen und Klassen verfügbar. In einer Session-Variablen lässt sich so ziemlich alles ablegen, was man auch in PHP selbst in Variablen speichern kann. Hierbei gilt es zu beachten, dass das Speichern von Link-IDs zu Dateien oder Datenbankverbindungen zwar natürlich technisch möglich, jedoch nur sehr bedingt sinnvoll ist: Schließlich werden die meisten Verbindungen beim Beenden des Skripts automatisch geschlossen und wären bei einem späteren Zugriffsversuch somit ungültig. Das Ablegen einer Instanz einer Klasse hingegen stellt kein Problem dar – wichtig ist hier lediglich, dass die Session erst nach der Definition der Klasse gestartet wird. Um einmal in die Session aufgenommene Daten wieder los zu werden, reicht ein einfaches unset() des entsprechenden Elements des Arrays $_SESSION / $HTTP_SESSION_VARS oder – falls die Variable via session_register() angemeldet wurde – der Aufruf von session_unregister().

Endlich Praxis

Kommen wir nach der grauen Theorie zu einem Anwendungsbeispiel mitten aus dem Leben: Ein Session-basiertes Login. Die im HTTP implementierte Basic-Auth-Methode (durch versenden des Header-Codes 401, www.php.net/manual/de/features.http-auth.php) ist verhältnismäßig unsicher, da mit ihr abgefragte Logindaten im System des Surfers zwischengespeichert werden und somit nur mit dem Beenden des Browers ein wirksames Abmelden zu realisieren ist. Hier spielt ein Session-System eine seiner Stärken aus: Durch einfaches Löschen bzw. Beenden der Session ist der Surfer auch schon abgemeldet. Da eine Session in ihrer Gültigkeit zudem zeitlich begrenzt ist, verfällt sie nach einem vorgegebenen Zeitrahmen ohne Nutzung automatisch. Bevor der Anwender nun unseren geschützten Bereich betreten darf, muss er sich erst einmal Anmelden. Hierfür verwenden wir das in start.php (Sie finden alle Listings auf der Heft-CD.) enthaltene einfache HTML-Formular. Das in der Action festgelegte Skript in Listing 1 [login.php] ist für die Überprüfung der Login-Daten und im Erfolgsfall für den Start einer neuen Session zuständig. Der Benutzer wird automatisch entweder in den geschützten Bereich oder zurück zur Login-Seite geschickt. Listing 1

Um nicht in jeder Seite den gleiche Code schreiben zu müssen, lagern wir den Code zur Überprüfung der Session und der in ihr gespeicherten Daten in ein include aus (session.inc.php, siehe CD). Um sicherzustellen, dass die übermittelte und von PHP bereits als gültig eingestufte SID auch vom gleichen Benutzer ist, überprüfen wir den Referer, die URL der vorherigen Seite sowie die IP des Benutzers. Stimmt die IP nicht mit der in der Session gespeicherten überein oder ist im Referer nichts von unserer Seite zu finden, so kann man mit großer Sicherheit davon ausgehen, dass hier eine SID entführt wurde. Als Folge dieser Erkenntnis erklären wir die Session als ungültig und stellen die Verarbeitung ein. Die mit inside.php angebotene Seite ist im geschützten Bereich und begrüßt den Anwender namentlich. Neben der Option sich gleich wieder abzumelden, wäre hier jetzt der richtige Ort, um zu eigenen Anwendungen und Funktionen zu verzweigen. Das mit der Option zum Abmelden verlinkte Skript (siehe Listing 2 [logout.php]) löscht alle Daten in der Session, beendet selbige und schickt den Surfer automatisch zur Anmeldeseite. Der Benutzer ist erfolgreich abgemeldet und auch über ein Zurückblättern in der History des Browsers lassen sich die vorherigen Seiten nicht mehr abrufen. Listing 2

Die hier gezeigten Beispiel-Listings setzen PHP ab der Version 4.1 voraus und sind auf der Heft-CD zu finden. Um die Beispiele mit früheren PHP-Versionen der Generation 4 zu verwenden, bedarf es nur einer kleinen Änderung: Tauschen Sie alle Vorkommen von $_SESSION,$_POST und $_GET durch die entsprechende $HTTP_*_VARS-Version aus und deaktivieren sie die register_globals-Funktion.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -