Teil von SELFHTML aktuell Teil von Artikel Teil von PHP

PHP:
Sessionbasiertes Loginsystem

nach unten Benjamin Wilfing
nach unten Hinweise zum Thema
nach unten Beispiel mit Erläuterungen
nach unten Weiterführende Links

Benjamin Wilfing

E-Mail: E-Mail benjamin.wilfing@selfhtml.org
Homepage-URL: deutschsprachige Seite http://wilfing-home.de/

Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!

nach obennach unten

Hinweise zum Thema

Wenn man Teile eines Internetauftritts vor neugierigen Augen schützen will, benötigt man ein wirksames System zur Zugangskontrolle. In vielen Fällen bietet sich hier die bekannte HTTP-Authentifizierung an, die man beispielsweise per Seite .htaccess-Datei umsetzen kann. Diese Methode hat aber den Nachteil, dass es auch in modernen Browsern immer noch keine praktikable Möglichkeit gibt, sich wieder abzumelden. Dieser Artikel soll zeigen, wie man Dokumente auf relativ einfache Weise sinnvoll schützen kann. Voraussetzung dafür ist ein Webserver mit PHP-Unterstützung.

Das System wird mittels Sessions umgesetzt (engl. Session = Sitzung). In PHP ist eine Session im Prinzip eine Datei, die sich im Dateisystem des Webservers befindet. In ihr sind Daten gespeichert, auf die man über den speziellen Array $_SESSION zugreifen kann. Jeder Benutzer, der mit seinem Browser eine Seite aufruft, die Sessions benutzt, bekommt nun vom Server eine einmalige Session-ID zugewiesen, über die er identifiziert werden kann. Dadurch ist es möglich, Daten benutzerbezogen zu speichern, die während einer Sitzung wiederverwendet werden können. Anwendungsmöglichkeiten sind zum Beispiel ein Warenkorb beim Einkaufen im Internet oder eine Administrationsoberfläche für ein Content Management System.

Das hier beschriebene Loginsystem umfasst die 3 Dateien login.php, logout.php und auth.php, welche sich alle im selben Verzeichnis befinden. Die Datei login.php beinhaltet sowohl das Formular zum Anmelden als auch die Routinen, um die Benutzerdaten zu verarbeiten und bei erfolgreicher Anmeldung entsprechende Daten in die Session zu speichern. Die Datei logout.php zerstört die Sitzungsdaten und meldet so den Benutzer ab. auth.php enthält den essentiellen Teil, nämlich die Überprüfung, ob der Benutzer aktuell angemeldet ist und somit berechtigt, das angeforderte Dokument anzusehen. Diese Datei wird in jedes zu schützende Dokument eingebunden.

nach obennach unten

Beispiel mit Erläuterungen

Die Datei login.php

<?php
     if ($_SERVER['REQUEST_METHOD'] == 'POST') {
      session_start();

      $username = $_POST['username'];
      $passwort = $_POST['passwort'];

      $hostname = $_SERVER['HTTP_HOST'];
      $path = dirname($_SERVER['PHP_SELF']);

      // Benutzername und Passwort werden überprüft
      if ($username == 'benjamin' && $passwort == 'geheim') {
       $_SESSION['angemeldet'] = true;

       // Weiterleitung zur geschützten Startseite
       if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') {
        if (php_sapi_name() == 'cgi') {
         header('Status: 303 See Other');
         }
        else {
         header('HTTP/1.1 303 See Other');
         }
        }

       header('Location: http://'.$hostname.($path == '/' ? '' : $path).'/index.php');
       exit;
       }
      }
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
 <head>
  <title>Geschützter Bereich</title>
 </head>
 <body>
  <form action="login.php" method="post">
   Username: <input type="text" name="username" /><br />
   Passwort: <input type="password" name="passwort" /><br />
   <input type="submit" value="Anmelden" />
  </form>
 </body>
</html>

Erläuterung:

Der Programmcode in dieser Datei ist für den Anmeldeprozess zuständig. Das Skript prüft zuerst, ob der Benutzer schon angemeldet ist. Ist das nicht der Fall, wird ein Formular angezeigt, welches Benutzername und Passwort über die Methode Seite POST wieder an die Datei login.php sendet, um dann wiederum weiterverarbeitet zu werden. Hier sind sowohl Benutzername als auch Passwort im Quelltext fest einprogrammiert – denkbar wäre aber zum Beispiel auch die Abfrage von Benutzerdaten aus einer Datenbank oder einer Textdatei, so dass mehrere Benutzernamen eingerichtet werden können.

Wurden Benutzername und Passwort korrekt eingegeben, wird in der am Anfang des Skripts geöffneten Session eine Variable mit dem Namen angemeldet und dem Wert true gespeichert.

Im nächsten Schrit wird der Benutzer auf die Datei index.php weitergeleitet. Dies geschieht mittels der Funktion header('Location: ...'). Da die Location-Anweisung einen vollständigen URI erwartet, man diesen vielleicht aber aus Bequemlichkeit nicht für jedes Projekt ändern will oder den künftigen URI noch nicht kennt, wird er aus Servervariablen zusammengebaut, so dass man nur noch den letzten Teil an seine Bedürfnisse anpassen muss. Im Beispiel befindet sich die Datei index.php im selben Verzeichnis wie login.php.

Waren Benutzername oder Passwort falsch, wird wieder das Login-Formular angezeigt – der Benutzer muss die Zugangsdaten erneut eingeben.

Der HTTP Statuscode 303 See Other wird hier aus Gründen der Standardkonformität gesendet: Bei einem Location-Header sendet PHP standardmäßig den Statuscode 302, nur ist hier nicht definiert, ob der nachfolgende Weiterleitungsrequest per POST oder GET getätigt werden soll. HTTP/1.1 wurde daher unter anderem um die Statuscodes 303 und 307 erweitert, die genau das festlegen. Ältere Browser, die nur HTTP/1.0 implementiert haben, bleiben bei der Abfrage nach $_SERVER['SERVER_PROTOCOL'] außen vor, bekommen so den obligatorischen Statuscode 302 und reagieren darauf, wie sie programmiert wurden. In fast allen dieser älteren Browser wird die nächste Seite dann per GET angefordert.

Wichtig:

Achten Sie darauf, dass die Passwörter gut gesichert sind. Der beste Passwortschutz nützt nichts, wenn Passwörter im Klartext gespeichert sind und im schlimmsten Fall sogar über den Browser gelesen werden können. Auch im Beispiel ist darauf zu achten, dass die Datei login.php nicht für andere Systembenutzer auf dem Webserver lesbar ist. Am bequemsten ist es, wenn eine (z.B. MySQL-)Datenbank mit eigenem Benutzernamen zur Verfügung steht, auf die niemand anderes Zugriff hat. Um zusätzlich an Sicherheit zu gewinnen, kann es außerdem sinnvoll sein, die Passwörter zusätzlich zu verschlüsseln, bzw. nur dessen Hash-Wert zu speichern, beispielsweise per md5-Funktion.

Die Datei logout.php

<?php
     session_start();
     session_destroy();

     $hostname = $_SERVER['HTTP_HOST'];
     $path = dirname($_SERVER['PHP_SELF']);

     header('Location: http://'.$hostname.($path == '/' ? '' : $path).'/login.php');
?>

Erläuterung:

Die Datei logout.php ist einzig und allein dafür zuständig, die Session - und damit die Information, dass der Benutzer angemeldet ist - zu zerstören. Danach wird der Benutzer wieder zum Anmeldeformular weitergeleitet.

Die Datei auth.php

<?php
     session_start();

     $hostname = $_SERVER['HTTP_HOST'];
     $path = dirname($_SERVER['PHP_SELF']);

     if (!isset($_SESSION['angemeldet']) || !$_SESSION['angemeldet']) {
      header('Location: http://'.$hostname.($path == '/' ? '' : $path).'/login.php');
      exit;
      }
?>

Erläuterung:

Dies ist die Datei, die später in jede zu schützende Seite eingebunden werden muss. Es wird dann immer überprüft, ob die Sessionvariable angemeldet existiert und ihr Wert true ist. Falls das nicht der Fall ist, wird der Benutzer wieder zum Anmeldeformular weitergeleitet. Wichtig ist hier die exit-Anweisung nach der Weiterleitung, damit kein weiterer Code ausgeführt werden kann und das Skript sofort beendet wird.

Beispiel: Die geschützte Datei index.php

<?php include('auth.php'); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
 <head>
  <title>Geschützter Bereich</title>
 </head>
 <body>
  <h1>Herzlichen Glückwunsch!</h1>
  <p>Sie sind nun angemeldet.</p>
  <p>Sie können sich auch wieder <a href="logout.php">abmelden</a>.</p>
 </body>
</html>

Erläuterung:

Die erste und einzige Anweisung, die eine geschützte Seite enthalten muss, ist der Befehl zum Einbinden der Datei auth.php, nämlich include in der ersten Zeile. Der Rest der Datei kann eine ganz normale HTML-Seite sein. Wenn Sie mehrere Dokumente schützen wollen, müssen Sie diese Zeile einfach am Anfang jeder Datei einfügen. Solange der Benutzer sich nicht explizit abgemeldet hat - ein Link zum Abmelden sollte natürlich immer vorhanden sein - ist keine weitere Eingabe des Passworts nötig.

Beachten Sie:

Die hier beschriebene Methode bringt natürlich auch gewisse Einschränkungen und Nachteile mit sich. Beispielsweise können im Gegensatz zur HTTP-Authentifizierung komplette Verzeichnisse nicht ohne weiteres geschützt werden, der Schutz beschränkt sich lediglich auf Dateien, die von PHP geparst werden – in der Regel also nur Textdokumente wie z.B. HTML- oder XML-Dateien.

nach obennach unten

Weiterführende Links

Die folgenden Stellen werden empfohlen, um das obige Beispiel besser zu verstehen, oder um weitere Möglichkeiten und Details zu erfahren.

deutschsprachige Seite Das PHP-Handbuch: Session-Funktionen
deutschsprachige Seite Das PHP-Handbuch: die Funktion header
deutschsprachige Seite DCLP-FAQ: Wie kann ich Passwörter sicher speichern?
englischsprachige Seite Weiterleitungen nach POST-Requests

Teil von SELFHTML aktuell Teil von Artikel Teil von PHP

© 2007 bereichsübergreifende Seite Impressum