0, 'path' => '/', 'httponly' => true, 'samesite' => 'Strict', // 'secure' => true, ]); session_start(); // Pokud je uživatel přihlášen, přesměrujeme ho 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 // ------------------------------------------------------------ // Tuto hlášku zobrazíme vždy po odeslání formuláře – // bez ohledu na to, zda email existuje $zprava_po_odeslani = 'Pokud je zadaný email registrován, ' . 'přijde ti na něj odkaz pro obnovu hesla. ' . 'Odkaz bude platný 1 hodinu.'; $odeslano = false; $chyba = ''; 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 zkusit znovu.'; } if (empty($chyba)) { $email = trim($_POST['email'] ?? ''); if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { $chyba = 'Zadejte platnou emailovou adresu.'; } } if (empty($chyba)) { // Vyhledáme uživatele v DB $stmt = $pdo->prepare(" SELECT `id` FROM `" . DB_TABULKA_UZIVATELE . "` WHERE `email` = :email LIMIT 1 "); $stmt->execute([':email' => $email]); $uzivatel = $stmt->fetch(); if ($uzivatel) { // -- Uživatel existuje – vytvoříme reset token ---- // Smažeme případné staré (nepoužité) tokeny tohoto uživatele $stmt2 = $pdo->prepare(" DELETE FROM `" . DB_TABULKA_RESET . "` WHERE `uzivatel_id` = :uzivatel_id "); $stmt2->execute([':uzivatel_id' => $uzivatel['id']]); // Vygenerujeme nový token // Do emailu jde plaintext, do DB jde jen hash $token = bin2hex(random_bytes(32)); // 64 znaků hex $token_hash = password_hash($token, PASSWORD_DEFAULT); $expiruje = date('Y-m-d H:i:s', time() + 3600); // 1 hodina $stmt3 = $pdo->prepare(" INSERT INTO `" . DB_TABULKA_RESET . "` (`uzivatel_id`, `token_hash`, `expiruje`) VALUES (:uzivatel_id, :token_hash, :expiruje) "); $stmt3->execute([ ':uzivatel_id' => $uzivatel['id'], ':token_hash' => $token_hash, ':expiruje' => $expiruje, ]); $reset_id = $pdo->lastInsertId(); // Sestavíme odkaz pro obnovu hesla // Odkaz obsahuje ID záznamu a plaintext token $odkaz = PROJEKT_URL . '/auth/nove_heslo.php' . '?id=' . urlencode($reset_id) . '&token=' . urlencode($token); // Odešleme email $predmet = 'Obnova hesla – ' . PROJEKT_NAZEV; $text = "Ahoj,\n\n" . "požádal(a) jsi o obnovu hesla na " . PROJEKT_NAZEV . ".\n\n" . "Pro nastavení nového hesla klikni na tento odkaz:\n" . $odkaz . "\n\n" . "Odkaz je platný 1 hodinu.\n\n" . "Pokud jsi o obnovu hesla nežádal(a), tento email ignoruj.\n\n" . PROJEKT_NAZEV; odesli_mail($email, $predmet, $text); } // Zobrazíme stejnou hlášku bez ohledu na existenci emailu $odeslano = true; } } // ------------------------------------------------------------ // HTML VÝSTUP // ------------------------------------------------------------ ?>
Chyba:
Zadej svůj email a pošleme ti odkaz pro obnovu hesla.