Skip to main content

Login & Authetifizierung

Sessions und Cookies anwenden
Der Hintergrund

Du weisst, wie Daten von einem Formular an den Server übermittelt und dort ausgewertet werden. Für ein Login stellt sich nun aber die Frage, wie der Server sich nach der Autentifizierung an einen Besucher erinnern kann - wir möchten schliesslich nicht bei jedem Seitenaufruf von neuem beweisen müssen, dass wir berechtigt sind. Darum benötigst du einen temporären Speicher für den Loginstatus - sozusagen ein Kurzzeitgedächtnis für deine Webapplikation. Dazu kannst du Sessions verwenden.

kalender 1

Eine Session ist eine Methode, um Daten über mehrere Seitenaufrufe hinweg zu speichern. Sie wird auf dem Server gespeichert und ist mit einer eindeutigen Session-ID verknüpft. Die Session-ID ist ein String, der keine Daten enthält, mit der jedoch die Session dem Besucher zugeordnet werden kann. Sie wird bei Erstellung der Session erzeugt und mit der Antwort im Response Header an den Browser geschickt. Im Browser des Benutzers wird die ID als Cookie gespeichert und bei jedem Aufruf im Request Header mitgeschickt. So wird es möglich, für jeden Besucher ein eigenes Kurzzeitgedächtnis auf dem Server zu verwalten und abzurufen.

Session lifetime und Gültigkeit

Bitte beachte: Sessions sind wirklich nur ein temporärer Speicher. Eine Session ist so lange gültig, wie das zugehörige Session Cookie verfügbar ist, und der Speicher auf dem Server besteht. Das Cookie wird vom Browser des Besuchers verwaltet und üblicherweise bei dessen Schliessung gelöscht, der Besucher kann es theoretisch aber auch vorher löschen. Der Sessionspeicher wird vom Server verwaltet. Zum Beispiel wird der Speicher zeitlich beschränkt - die maximale Lebenszeit einer Session ist in der PHP Konfiguration (session.gc_maxlifetime in php.ini) definiert, und beträgt im Normalfall 24 Minuten. Das heisst, wenn du eine Session erzeugst, und mehr als 24 Minuten wartest, wird sie vom Server gelöscht sein und nicht mehr existieren - im Falle eines Loginstatus wird der Benutzer danach nicht mehr einggeloggt sein. Jeder Zugriff auf die Session innerhalb der definiterten Session Lifetime aktualisiert jedoch die Gültigkeitsdauer der Session. Das bedeutet, dass die Session aktiv bleibt, solange regelmäßig (z.B. durch dein PHP Skript) darauf zugegriffen wird. 

Bei AJAX Applikationen, wo die Seite oft nicht als ganzes neu geladen wird, kann ein so genanntes "keepAlive" JavaScript regelmässig einen AJAX-Call an ein PHP Skript machen, welches session_start() noch einmal ausführt. So läuft die Session auch bei längerer Nutzung nur auf dem Client nicht ab.  

Dafür solltest du in jedem Skript, das Sessionzugriff haben soll, folgende Zeile zu Beginn des Skripts ausführen. Hierbei wird auf die existierende Session zugegriffen, wenn keine besteht, wird eine neue Session erstellt, und deren ID an den Browser geschickt.

session_start();

Sobald der Sessionzugriff eröffnet ist, steht für dich ein Super Global Array zur Verfügung, welches du mit print_r() einsehen kannst. Mit diesem Session-Array wirst du danach arbeiten. Du kannst Daten einfach hineinschreiben und wieder auslesen, den Rest übernimmt der Server für dich.

// testausgabe (Monitor) für die Sessiondaten
echo '<pre>';
print_r( $_SESSION );
echo '</pre>';

Anwendungen

Sessions werden für verschiedene Zwecke eingesetzt - immer dann, wenn Informationen kurzzeitig gespeichert werden müssen. Beispiele:

  • Loginstatus (nach dem Login wird der Status und weitere Erkennungsmerkmale in der Session gespeichert und bei jedem Zugriff abgerufen)
  • Form Token (Herkunfstprüfung für deine Formulardaten - ein "Geheimwort", mit dem sich ein Formular autentifizieren kann, und so dein Skript vor dem Verarbeiten von Formulardaten schützt, die von einem fremden Server, z.B. von einem Hacker an dein Skript abgeschickt wurden)
  • Warenkorb (die ID's der gewählten Produkte und die gewünschte Menge werden in der Session gespeichert, bis die Bestellung abgeschickt wird)
  • Benutzereinstellungen (Sprache, Darstellung etc. werdne für diesen Besuch gespeichert)
  • Fehlermeldungen (Fehlermeldungen werden in der Session gespeichert, damit sie auch erst nach einem Redirect ausgegeben werden können - dies ist in grösseren Applikationen und CMS Systemen oft der Fall)
  • Brute Force Schutz (Ein Zähler wird in einer Session gespeichert und bei jedem ungültigen Loginversuch erhöht, damit nach einem festgelegten Maximum das Login komplett gesperrt werden kann)   

So geht's

Zur Vorbereitung kannst du dir das loginformular.zip herunterladen und im Testserver speichern. Die Verarbeitung machst du in der gleichen Datei. 

  1. Erstelle nun einen PHP Block oberhalb des HTML und eröffne als erstes den Sessionzugriff:
    <?php
    session_start(); // Sessionzugriff
    ?>
  2. Betrachte nun das HTML. Es enthält schon ein wenig PHP-Logik. Diese zeigt klar auf was das Ziel des Scripts sein sollte: wenn ein Benutzer eingeloggt ist, soll er eine Willkommensnachricht und einen Logout Button sehen, sonst wird ihm das Loginformular angezeigt. Hierfür soll während dem Loginprozess und bei der Prüfung, ob der User eingeloggt ist, die Variable $isLoggedIn entweder true (eingeloggt) oder false (nicht eingeloggt) erhalten. Ist jemand eingeloggt, wird er mit $username begrüsst - es gilt also, den Benuzternamen in dieser Variablen zur Verfügung zu stellen. Ausserdem gibt es auch die Variablen $hasError und $errorMessages, die du schon von der Formularvalidierung kennst. Du kannst diese Variablen gleich zu beginn initialisieren mit einem Anfangswert:
    $isLoggedIn = false;
    $username = '';
    $hasError = false;
    $errorMessages = array();
  3. Erstelle ebenfalls am Anfang Variablen für Benutzernamen und Passwort - da du keine Datenbank abfragst in dieser Übung, erstellen wir "Dummy credentials".
    // Dummy credentials
    $valid_username = 'Terry';
    $valid_password = 'test1234';
  4. Prüfe nun (unterhalb der Variablen) ob das Loginformular verarbeitet werden soll. Dies soll nur geschehen, wenn der Besucher noch nicht eingeloggt ist, aber Formulardaten per POST gesendet hat.
  5. if (!$isLoggedIn && $_SERVER['REQUEST_METHOD'] == 'POST') {
        // Loginprüfung / Loginprozess kommt hier hin
    }
  6. Prüfe nun die Logindaten aus POST, indem du sie mit den gespeicherten Dummydaten vergleichst, und wenn dies korrekt ist, schreibe den Usernamen ins Session Array. So kannst du später den Benutzer begrüssen.
    if ($_POST['username'] === $valid_username && $_POST['password'] === $valid_password) {
        // Name in Session schreiben für spätere Begrüssung
        $_SESSION['username'] = $valid_username;
    }
  7. Füge nun noch ein Fehlerhandling hinzu für den Fall, dass die Logindaten nicht korrekt sind. In diesem Fall braucht es weder Validierung noch Bereinigung. Deine komplette Loginprüfung sieht dann so aus:
    if ($_POST['username'] === $valid_username && $_POST['password'] === $valid_password) {
        // Name in Session schreiben für spätere Begrüssung
        $_SESSION['username'] = $valid_username;
    } else {
        $hasError = true;
        $errorMessages[] = 'Benutzername oder Passwort falsch';
    }
  8. Damit du nun die Variablen im HTML nutzen kannst, um zu entscheiden, ob ein Benutzer eingeloggt ist, füge noch eine letzte Abfrage hinzu, bei der du den Benutzernamen in der Session abfragst. Schreibe diese Abfrage VOR der Loginprüfung, damit der ganze Rest gar nicht mehr ausgeführt wird, wenn dein Benutzer schon eingeloggt ist. Du überschreibst dabei die anfangs erstellten Variablen $isLoggedIn und $username einfach mit neuen Werten:
    // Prüfen auf einen eingeloggten benutzer
    if ( isset($_SESSION['username']) ) {
        $isLoggedIn = true; // Loginstatus ändern
        $username = $_SESSION['username']; // Usernamen aus Session auslesen
    }
  9. Nun solltest du je nach Loginstatus das Formular oder eine Begrüssung sehen. Schreibe nun noch das Logout Skript. Hier könntest du mit den Funktionen session_unset() und session_destroy() die gesamte Session beenden (der Speicherplatz und die Daten werden gelöscht). Da deine Applikation aber vielleicht noch weitere Daten in der Session speichert, ist dies oft kein guter Weg. Nutze deshalb die möglichkeit, nur den für den Logincheck relevanten Eintrag aus der Session zu entfernen. 
    session_start(); // Zugriff auf die Session
    unset($_SESSION['username']); // username aus Session löschen
  10. Zuallerletzt kannst du nach dem löschen des Benutzernamens noch auf die HTML Seite mit  dem Login zurück leiten mit einer Umleitung:
    header('Location: login.php'); // umleitung zu login.php
    exit(); // Abbruch des Skripts für alle Fälle

Tips und Links

Validierung eines Loginformulars

Loginformulare sind die einzigen Formulare, deren User Input du kaum validieren musst. Denn es geht nicht darum, Daten in Empfang zu nehmen, sondern lediglich, diese gegen die schon gespeicherten zu prüfen. Logindaten sind entweder korrekt oder falsch, und du möchtest keine weiteren Hinweise geben, wenn etwas nicht korrekt ist (um nicht dem Hacker zu helfen). 

Zum Speichern des Passworts

Normalerweise gilt der Ansatz: Logindaten müssen sicher gespeichert werden und NIE IM KLARTEXT lesbar abgelegt werden. Für die Sicherheit wird eine Datenbank empfohlen, weil hier ohne Authentifizierung gar kein Zugriff möglich ist. Hast du jedoch eine ganz kleine Applikation, die tatsächlich nur einen einzigen Benutzer benötigt (Beispiel: Onepager deines Bruders für seine Hochzeit, er möchte lediglich Bilder hochladen können), kannst du dies - ganz nach dem "Quick&Dirty Ansatz" auch ohne Datenbank machen. Zum Schutz des Passwortes solltest du aber nicht auf Password Hashing verzichten, denn Passworte sollten weder im Klartext, noch wiederherstellbar abgelegt werden. Wenn du mehr wissen willst darüber, lese dir dazu diesen Beitrag über Password Hashing durch. 

Sessiondaten - was ist drin?

Du arbeitest hier wieder mit einem Super Global Array. Mach dir nicht die Mühe, dir die Session vorzustellen - nutze print_r() während dem Entwickeln, um genau zu sehen, wie deine Sessiondaten aussehen. Weil du im Laufe deines Scripts mit den Sessiondaten arbeitest, sollte print_r ganz am Ende deines Skripts stehen, gleich vor dem HTML.  

Mittel

Daten in Sessions speichern

Realisiere ein einfaches Login und Logout Skript mittels Sessionspeicher