0, 'path' => '/', 'httponly' => true, 'samesite' => 'Strict', // 'secure' => true, ]); session_start(); // Pokud je uživatel již přihlášen, přesměrujeme ho rovnou dál if (isset($_SESSION['uzivatel_id'])) { header('Location: ' . AUTH_REDIRECT_PO_PRIHLASENI); exit; } // ------------------------------------------------------------ // CSRF TOKEN // ------------------------------------------------------------ if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } $csrf_token = $_SESSION['csrf_token']; // ------------------------------------------------------------ // ZPRACOVÁNÍ FORMULÁŘE // ------------------------------------------------------------ $chyba = ''; $email_hodnota = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { // -- Ověření CSRF tokenu ---------------------------------- $csrf_z_formulare = $_POST['csrf_token'] ?? ''; if (!hash_equals($csrf_token, $csrf_z_formulare)) { $chyba = 'Neplatný požadavek. Zkuste stránku obnovit a přihlásit se znovu.'; } if (empty($chyba)) { $email = trim($_POST['email'] ?? ''); $heslo = $_POST['heslo'] ?? ''; $zapamatovat = isset($_POST['zapamatovat']); $email_hodnota = htmlspecialchars($email); if (empty($email) || empty($heslo)) { $chyba = 'Zadejte email a heslo.'; } } if (empty($chyba)) { // -- Kontrola brute force ----------------------------- $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; $okno_od = date('Y-m-d H:i:s', time() - BRUTE_OKNO); $stmt = $pdo->prepare(" SELECT COUNT(*) AS pocet FROM `" . DB_TABULKA_BRUTE . "` WHERE (`ip_adresa` = :ip OR `email` = :email) AND `cas` > :okno_od "); $stmt->execute([ ':ip' => $ip, ':email' => $email, ':okno_od' => $okno_od, ]); $pocet_pokusu = $stmt->fetch()['pocet']; if ($pocet_pokusu >= BRUTE_MAX_POKUSU) { $chyba = 'Příliš mnoho neúspěšných pokusů. Zkuste to prosím za chvíli.'; } } if (empty($chyba)) { // -- Ověření emailu a hesla v DB ---------------------- $stmt = $pdo->prepare(" SELECT `id`, `email`, `heslo`, `admin` FROM `" . DB_TABULKA_UZIVATELE . "` WHERE `email` = :email LIMIT 1 "); $stmt->execute([':email' => $email]); $uzivatel = $stmt->fetch(); // I když uživatel neexistuje, zavoláme password_verify na fiktivní // hash – aby útočník nemohl podle doby odpovědi poznat, zda email existuje $fiktivni_hash = '$2y$10$abcdefghijklmnopqrstuuABCDEFGHIJKLMNOPQRSTUVWXYZ01234'; $hash_k_overeni = $uzivatel ? $uzivatel['heslo'] : $fiktivni_hash; $heslo_ok = password_verify($heslo, $hash_k_overeni); if (!$uzivatel || !$heslo_ok) { // Zapíšeme neúspěšný pokus $stmt2 = $pdo->prepare(" INSERT INTO `" . DB_TABULKA_BRUTE . "` (`ip_adresa`, `email`) VALUES (:ip, :email) "); $stmt2->execute([ ':ip' => $ip, ':email' => $email, ]); $chyba = 'Nesprávný email nebo heslo.'; } else { // -- Přihlášení úspěšné --------------------------- session_regenerate_id(true); $_SESSION['uzivatel_id'] = $uzivatel['id']; $_SESSION['email'] = $uzivatel['email']; $_SESSION['admin'] = (bool) $uzivatel['admin']; $_SESSION['posledni_aktivita'] = time(); $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); // -- Remember me ---------------------------------- if ($zapamatovat) { $selector = bin2hex(random_bytes(16)); $token = bin2hex(random_bytes(32)); $token_hash = password_hash($token, PASSWORD_DEFAULT); $expiruje = date('Y-m-d H:i:s', time() + REMEMBER_EXPIRACE); $stmt3 = $pdo->prepare(" INSERT INTO `" . DB_TABULKA_TOKENY . "` (`uzivatel_id`, `selector`, `token_hash`, `expiruje`) VALUES (:uzivatel_id, :selector, :token_hash, :expiruje) "); $stmt3->execute([ ':uzivatel_id' => $uzivatel['id'], ':selector' => $selector, ':token_hash' => $token_hash, ':expiruje' => $expiruje, ]); $cookie_expirace = time() + REMEMBER_EXPIRACE; setcookie('auth_selector', $selector, [ 'expires' => $cookie_expirace, 'path' => '/', 'httponly' => true, 'samesite' => 'Strict', // 'secure' => true, ]); setcookie('auth_token', $token, [ 'expires' => $cookie_expirace, 'path' => '/', 'httponly' => true, 'samesite' => 'Strict', // 'secure' => true, ]); } // -- Přesměrování po přihlášení ------------------- $redirect = $_SESSION['redirect_po_prihlaseni'] ?? AUTH_REDIRECT_PO_PRIHLASENI; unset($_SESSION['redirect_po_prihlaseni']); header('Location: ' . $redirect); exit; } } } // ------------------------------------------------------------ // HTML VÝSTUP // ------------------------------------------------------------ ?>
Chyba: