0, 'path' => '/', 'domain' => '', 'secure' => $secure, 'httponly' => true, 'samesite' => 'Lax', ]; } public static function verlange(): void { self::startSession(); $benutzerId = $_SESSION['user_id'] ?? null; $anmeldung = $_SESSION['login_time'] ?? 0; if (!$benutzerId || (time() - (int)$anmeldung) > self::SESSION_LAUFZEIT) { $_SESSION = []; session_destroy(); View::redirect('/login'); } } public static function anmelden(int $benutzerId): void { self::startSession(); session_regenerate_id(true); $_SESSION['user_id'] = $benutzerId; $_SESSION['login_time'] = time(); } public static function abmelden(): void { self::startSession(); $_SESSION = []; if (ini_get('session.use_cookies')) { $p = session_get_cookie_params(); setcookie(session_name(), '', time() - 42000, $p['path'], $p['domain'], (bool)$p['secure'], (bool)$p['httponly']); } session_destroy(); } public static function benutzerId(): ?int { return isset($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : null; } public static function benutzer(): ?array { $id = self::benutzerId(); return $id === null ? null : Benutzer::find($id); } public static function csrfToken(): string { self::startSession(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } public static function pruefeCsrfToken(string $token): void { self::startSession(); if (!self::istGueltigerCsrfToken($token)) { http_response_code(403); exit('CSRF-Token ungültig.'); } } /** Reiner Vergleich ohne Seiteneffekt, damit isoliert testbar. */ public static function istGueltigerCsrfToken(string $token): bool { $gespeichert = $_SESSION['csrf_token'] ?? ''; return $gespeichert !== '' && hash_equals($gespeichert, $token); } }