EMZETT.
Login

Kurz: Bei jeder Anfrage startet PHP das Skript, erzeugt die Antwort und beendet sich wieder (shared nothing). Dabei füllt PHP automatisch Superglobals:

Teil des Kurses PHP

Kapitel 12 von 15 im Kurs PHP (Abschnitt „Web“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Wie PHP im Web läuft

Bei jeder Anfrage startet PHP das Skript, erzeugt die Antwort und beendet sich wieder (shared nothing). Dabei füllt PHP automatisch Superglobals:

VariableInhalt
$_GETParameter aus der URL (?name=Mia)
$_POSTFormulardaten aus dem Body
$_SERVERAnfrage-Infos (REQUEST_METHOD, REQUEST_URI, HTTP_HOST)
$_COOKIECookies
$_SESSIONSitzungsdaten (nach session_start())
$_FILESDatei-Uploads

Zum Ausprobieren: php -S localhost:8000 im Projektordner und http://localhost:8000/formular.php öffnen.

Ein Formular verarbeiten

formular.php

<?php
declare(strict_types=1);
 
$fehler = [];
$name = "";
 
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $name = trim($_POST["name"] ?? "");
    $alter = filter_input(INPUT_POST, "alter", FILTER_VALIDATE_INT, ["options" => ["min_range" => 0, "max_range" => 120]]);
 
    if ($name === "") $fehler[] = "Name fehlt.";
    if ($alter === false || $alter === null) $fehler[] = "Alter ungültig.";
 
    if (!$fehler) {
        // speichern ... dann weiterleiten (Post/Redirect/Get)
        header("Location: /danke.php");
        exit;
    }
}
?>
<form method="post">
    <label>Name <input name="name" value="<?= htmlspecialchars($name) ?>"></label>
    <label>Alter <input name="alter" type="number"></label>
    <button>Senden</button>
</form>
<?php foreach ($fehler as $f): ?>
    <p class="fehler"><?= htmlspecialchars($f) ?></p>
<?php endforeach; ?>

Regeln für Formulare:

  1. Validieren auf dem Server (Browser-Prüfung ist nur Komfort)
  2. Escapen bei der Ausgabe (htmlspecialchars)
  3. Post/Redirect/Get: Nach dem Speichern umleiten, damit “Neu laden” nichts doppelt sendet

Sessions und Cookies

Eine Session merkt sich Daten pro Besucher auf dem Server; im Browser liegt nur die Session-ID als Cookie.

login.php

<?php
session_start([
    "cookie_httponly" => true,
    "cookie_samesite" => "Lax",
    "cookie_secure" => true,       // nur über HTTPS
]);
 
if ($_SERVER["REQUEST_METHOD"] === "POST") {
    // Passwort immer gehasht prüfen
    if (password_verify($_POST["passwort"] ?? "", $gespeicherterHash)) {
        session_regenerate_id(true);          // gegen Session-Fixation
        $_SESSION["nutzer_id"] = $nutzerId;
    }
}
 
$_SESSION["besuche"] = ($_SESSION["besuche"] ?? 0) + 1;
setcookie("theme", "dunkel", ["expires" => time() + 86400 * 30, "path" => "/", "httponly" => true, "samesite" => "Lax"]);
 
// Abmelden:
// $_SESSION = []; session_destroy();

Passwörter richtig speichern

Passwörter werden nie im Klartext oder mit md5/sha1 gespeichert, sondern mit einem langsamen Hash und Salt:

<?php
$hash = password_hash("geheim123", PASSWORD_DEFAULT);       // Bcrypt/Argon2, Salt automatisch
echo strlen($hash) >= 60 ? "Hash ok" : "kurz", " ", str_starts_with($hash, '$2y$') ? "bcrypt" : "anderer", "\n";
var_dump(password_verify("geheim123", $hash), password_verify("falsch", $hash));
var_dump(password_needs_rehash($hash, PASSWORD_DEFAULT));
echo bin2hex(random_bytes(4)) !== "" ? "Zufall ok" : "", " ", random_int(5, 5), " ", hash("sha256", "abc"), "\n";

Ausgabe:

Hash ok bcrypt
bool(true)
bool(false)
bool(false)
Zufall ok 5 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

Die wichtigsten Angriffe und Gegenmittel

AngriffGegenmittel in PHP
SQL-InjectionPrepared Statements (PDO)
XSS (Skript im HTML)htmlspecialchars($text, ENT_QUOTES, 'UTF-8') bei jeder Ausgabe
CSRF (fremde Seite löst Aktion aus)CSRF-Token im Formular, SameSite-Cookies
Session-Fixation/-Diebstahlsession_regenerate_id(true), httponly, secure
Unsichere UploadsTyp/Größe prüfen, neuen Namen vergeben, außerhalb des Webroots speichern
Schwache Passwörterpassword_hash / password_verify
Offene Fehlerausgabedisplay_errors=0 in Produktion
Include aus Nutzereingabenie include $_GET['seite'] (Pfad-/Code-Einschleusung)

CSRF-Token

<?php
session_start();
// Beim Anzeigen des Formulars
$_SESSION["csrf"] ??= bin2hex(random_bytes(16));
$token = $_SESSION["csrf"];
echo '<input type="hidden" name="csrf" value="', strlen($token), ' Zeichen">', "\n";   // im echten Formular: den Token selbst ausgeben
 
// Beim Verarbeiten (simuliert)
$gesendet = $token;
var_dump(hash_equals($_SESSION["csrf"], $gesendet));        // zeitkonstanter Vergleich

Ausgabe:

<input type="hidden" name="csrf" value="32 Zeichen">
bool(true)

Eine einfache Antwort als API

api.php

<?php
header("Content-Type: application/json; charset=utf-8");
$method = $_SERVER["REQUEST_METHOD"];
 
if ($method === "GET") {
    echo json_encode(["status" => "ok", "zeit" => date(DATE_ATOM)]);
} elseif ($method === "POST") {
    $body = json_decode(file_get_contents("php://input"), true, 512, JSON_THROW_ON_ERROR);
    http_response_code(201);
    echo json_encode(["empfangen" => $body]);
} else {
    http_response_code(405);
    echo json_encode(["fehler" => "Methode nicht erlaubt"]);
}

Merke

  • Pro Anfrage läuft das Skript neu; Superglobals liefern die Eingaben
  • Eingaben validieren, Ausgaben escapen, Datenbank mit Prepared Statements
  • Sessions mit session_start, httponly/secure/samesite, session_regenerate_id
  • Passwörter: password_hash und password_verify
  • CSRF-Token und hash_equals, Fehleranzeige in Produktion aus
  • Post/Redirect/Get nach dem Speichern

Übungsaufgabe

Baue ein Kontaktformular mit Validierung, CSRF-Token und Anzeige der Fehler.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Datenbanken mit PDO

Weiter: Composer, Namespaces und Tests

Alle Kapitel: PHP im Überblick