0, 'path' => '/', 'secure' => !empty($_SERVER['HTTPS']), 'httponly' => true, 'samesite' => 'Lax', ]); session_name('PSLAUNCHER_ADMIN'); session_start(); } if (!isset($_SESSION['csrf'])) $_SESSION['csrf'] = bin2hex(random_bytes(32)); } public static function isLoggedIn(): bool { return !empty($_SESSION['admin']); } public static function login(string $username, string $password, array $config): bool { $hash = $config['admin_password_hash'] ?? ''; if ($hash === '') return false; if (!password_verify($password, $hash)) return false; $_SESSION['admin'] = ['user' => $username, 'at' => time()]; // régénère l'ID après login pour éviter session fixation session_regenerate_id(true); $_SESSION['csrf'] = bin2hex(random_bytes(32)); return true; } public static function logout(): void { $_SESSION = []; if (ini_get('session.use_cookies')) { $p = session_get_cookie_params(); setcookie(session_name(), '', time() - 3600, $p['path'], $p['domain'] ?? '', $p['secure'], $p['httponly']); } session_destroy(); } public static function requireLogin(): void { self::start(); if (!self::isLoggedIn()) { header('Location: login.php'); exit; } } public static function csrfToken(): string { return $_SESSION['csrf'] ?? ''; } public static function checkCsrf(): void { $token = $_POST['csrf'] ?? ''; if (!hash_equals($_SESSION['csrf'] ?? '', $token)) { http_response_code(403); die('CSRF token invalid'); } } }