Sicherer Session- und Cookie-Login mit PHP und MySQL
3 Min. LesezeitProgrammieren & Entwickeln
Ein Login-Formular ist schnell gebaut – ein sicheres nicht ganz so schnell. Die gute Nachricht: PHP bringt alle nötigen Werkzeuge mit. Man muss sie nur kennen und konsequent einsetzen.
Wie ein Login technisch abläuft
HTTP ist zustandslos: Jeder Seitenaufruf steht für sich. Damit eine Anmeldung „hängen bleibt“, erzeugt PHP eine Session. Auf dem Server liegen die Daten der Sitzung, etwa die Benutzer-ID. Der Browser erhält nur eine lange Zufallskennung als Cookie und schickt sie bei jedem Aufruf mit. Wer diese Kennung stiehlt, übernimmt die Sitzung – deshalb drehen sich die meisten Schutzmaßnahmen darum, das Passwort und die Session-ID gut zu schützen.
Passwörter nie im Klartext speichern
Seit PHP 5.5 gibt es die Funktionen password_hash() und password_verify(). Sie erzeugen einen gesalzenen, bewusst langsamen Hash und kümmern sich um alle Details. Selbstgebaute Lösungen mit MD5 oder SHA-1 sind veraltet und in Sekunden zu knacken.
// bei der Registrierung
$hash = password_hash($passwort, PASSWORD_DEFAULT);
// beim Login
if (password_verify($eingabe, $hashAusDerDatenbank)) {
// Passwort stimmt
}
PASSWORD_DEFAULT wählt automatisch das aktuell empfohlene Verfahren. Mit password_needs_rehash() lassen sich alte Hashes beim nächsten erfolgreichen Login still aktualisieren. Die Datenbankspalte sollte deshalb großzügig bemessen sein, 255 Zeichen sind üblich.
SQL-Injection verhindern
Benutzereingaben dürfen nie direkt in eine SQL-Abfrage geklebt werden. Prepared Statements trennen Befehl und Daten sauber:
$stmt = $pdo->prepare('SELECT id, passwort_hash FROM benutzer WHERE email = ?');
$stmt->execute([$email]);
$benutzer = $stmt->fetch();
So kann eine präparierte Eingabe die Abfrage nicht verändern – egal, welche Zeichen sie enthält.
Die Session nach dem Login erneuern
Direkt nach erfolgreicher Anmeldung sollte die Session eine neue Kennung bekommen. Das verhindert „Session Fixation“, bei der ein Angreifer dem Opfer vorab eine bekannte ID unterschiebt.
session_start();
// ... Passwort geprüft ...
session_regenerate_id(true);
$_SESSION['benutzer_id'] = $benutzer['id'];
Cookie-Flags richtig setzen
Das Session-Cookie sollte drei Eigenschaften haben: HttpOnly (JavaScript kommt nicht heran, das erschwert Diebstahl per Cross-Site-Scripting), Secure (nur über HTTPS) und SameSite (schränkt das Mitsenden bei fremden Seiten ein). Seit PHP 7.3 lassen sich alle drei bequem per Array setzen:
session_set_cookie_params([
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();
Brute Force und Formulare absichern
Begrenze fehlgeschlagene Versuche pro Konto und pro IP-Adresse, zum Beispiel mit wachsenden Wartezeiten. Formulare, die etwas verändern, brauchen ein CSRF-Token: einen zufälligen Wert, der in der Session liegt und mit dem Formular mitgeschickt wird. Gegen automatisierte Registrierungen hilft zusätzlich ein Spam-Schutz, wie er im Beitrag über reCAPTCHA und Alternativen beschrieben ist.
„Angemeldet bleiben“ und Logout
Für eine dauerhafte Anmeldung gehört niemals das Passwort ins Cookie. Üblich ist ein zufälliges, langes Token, das in der Datenbank nur als Hash gespeichert wird und bei jeder Nutzung erneuert werden kann. Beim Logout werden die Session-Daten gelöscht, das Cookie entwertet und session_destroy() aufgerufen.
Checkliste
- HTTPS überall, auch auf der Login-Seite.
password_hash()statt eigener Hash-Verfahren.- Prepared Statements für jede Abfrage mit Eingaben.
- Neue Session-ID nach dem Login, Timeout für inaktive Sitzungen.
- Cookie-Flags HttpOnly, Secure und SameSite.
- Begrenzte Login-Versuche und CSRF-Tokens.
Wer tiefer einsteigen will, findet im PHP-Handbuch zu password_hash() und im OWASP Cheat Sheet zum Session-Management weitere Details. Allgemeine Regeln für die eigene Sicherheit als Nutzer stehen in den Cybersecurity-Grundlagen.