diff --git a/auth/login.php b/auth/login.php index 70f843e..754d524 100644 --- a/auth/login.php +++ b/auth/login.php @@ -26,11 +26,6 @@ if (isset($_SESSION['uzivatel_id'])) { // ------------------------------------------------------------ // CSRF TOKEN // ------------------------------------------------------------ -// CSRF token je náhodný řetězec, který se vygeneruje při načtení -// stránky a uloží do session. Formulář ho odešle jako skryté pole. -// Při zpracování formuláře ověříme, že token sedí – tím zabráníme -// útoku, kdy by cizí web odeslal formulář jménem přihlášeného -// uživatele. if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); @@ -41,29 +36,25 @@ $csrf_token = $_SESSION['csrf_token']; // ZPRACOVÁNÍ FORMULÁŘE // ------------------------------------------------------------ -$chyba = ''; // chybová hláška pro uživatele -$email_hodnota = ''; // předvyplnění emailového pole po chybě +$chyba = ''; +$email_hodnota = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { // -- Ověření CSRF tokenu ---------------------------------- $csrf_z_formulare = $_POST['csrf_token'] ?? ''; - // hash_equals porovnává řetězce v konstantním čase – - // chrání před timing útoky na 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)) { - // -- Načtení hodnot z formuláře ----------------------- - $email = trim($_POST['email'] ?? ''); - $heslo = $_POST['heslo'] ?? ''; + $email = trim($_POST['email'] ?? ''); + $heslo = $_POST['heslo'] ?? ''; $zapamatovat = isset($_POST['zapamatovat']); - $email_hodnota = htmlspecialchars($email); // pro předvyplnění pole + $email_hodnota = htmlspecialchars($email); - // -- Základní validace -------------------------------- if (empty($email) || empty($heslo)) { $chyba = 'Zadejte email a heslo.'; } @@ -72,9 +63,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (empty($chyba)) { // -- Kontrola brute force ----------------------------- - // Spočítáme neúspěšné pokusy z této IP adresy - // nebo pro tento email za poslední časové okno - $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; + $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; $okno_od = date('Y-m-d H:i:s', time() - BRUTE_OKNO); $stmt = $pdo->prepare(" @@ -91,7 +80,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $pocet_pokusu = $stmt->fetch()['pocet']; if ($pocet_pokusu >= BRUTE_MAX_POKUSU) { - // Nezradíme přesný důvod – jen obecná hláška $chyba = 'Příliš mnoho neúspěšných pokusů. Zkuste to prosím za chvíli.'; } } @@ -108,17 +96,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $stmt->execute([':email' => $email]); $uzivatel = $stmt->fetch(); - // Ověříme heslo pomocí password_verify(). - // DŮLEŽITÉ: 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'; + // 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); + $heslo_ok = password_verify($heslo, $hash_k_overeni); if (!$uzivatel || !$heslo_ok) { - // Přihlášení selhalo – zapíšeme neúspěšný pokus + // Zapíšeme neúspěšný pokus $stmt2 = $pdo->prepare(" INSERT INTO `" . DB_TABULKA_BRUTE . "` (`ip_adresa`, `email`) @@ -130,38 +116,27 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { ':email' => $email, ]); - // Obecná hláška – neříkáme, zda byl špatný email nebo heslo $chyba = 'Nesprávný email nebo heslo.'; } else { // -- Přihlášení úspěšné --------------------------- - - // Regenerujeme session ID – ochrana před session fixation - // (útočník mohl podstrčit uživateli konkrétní session ID) session_regenerate_id(true); - // Zapíšeme uživatele do session $_SESSION['uzivatel_id'] = $uzivatel['id']; $_SESSION['email'] = $uzivatel['email']; $_SESSION['admin'] = (bool) $uzivatel['admin']; $_SESSION['posledni_aktivita'] = time(); - - // Vygenerujeme nový CSRF token pro další požadavky - $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); // -- Remember me ---------------------------------- if ($zapamatovat) { - // Selector = veřejný identifikátor (jde do cookie i DB) - // Token = tajný řetězec (do cookie jde plaintext, - // do DB jen bcrypt hash) - $selector = bin2hex(random_bytes(16)); // 32 znaků hex - $token = bin2hex(random_bytes(32)); // 64 znaků hex - $token_hash = password_hash($token, PASSWORD_DEFAULT); - $expiruje = date('Y-m-d H:i:s', time() + REMEMBER_EXPIRACE); + $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); - // Uložíme token do DB $stmt3 = $pdo->prepare(" INSERT INTO `" . DB_TABULKA_TOKENY . "` (`uzivatel_id`, `selector`, `token_hash`, `expiruje`) @@ -175,9 +150,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { ':expiruje' => $expiruje, ]); - // Nastavíme cookie v prohlížeči - // Cookie obsahuje POUZE selector a token – žádné heslo, - // žádné ID, žádný příznak admin $cookie_expirace = time() + REMEMBER_EXPIRACE; setcookie('auth_selector', $selector, [ 'expires' => $cookie_expirace, @@ -196,8 +168,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } // -- Přesměrování po přihlášení ------------------- - // Pokud byl uživatel přesměrován z jiné stránky, - // vrátíme ho tam. Jinak jde na výchozí stránku. $redirect = $_SESSION['redirect_po_prihlaseni'] ?? AUTH_REDIRECT_PO_PRIHLASENI; unset($_SESSION['redirect_po_prihlaseni']); @@ -231,7 +201,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
-

@@ -271,10 +240,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {

-

Nemáš účet? Zaregistruj se.

+

Nemáš účet? Zaregistruj se.

-

Zapomněl jsi heslo?

+

Zapomněl jsi heslo?

\ No newline at end of file