Files
MSPPPPaM/auth/login.php
T

249 lines
7.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// ============================================================
// PŘIHLAŠOVACÍ STRÁNKA
// ============================================================
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/db.php';
// Spuštění session (stejné nastavení jako v auth.php)
session_name(SESSION_NAZEV);
session_set_cookie_params([
'lifetime' => 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
// ------------------------------------------------------------
?>
<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<title>Přihlášení <?php echo htmlspecialchars(PROJEKT_NAZEV); ?></title>
<?php if (AUTH_CSS !== ''): ?>
<link rel="stylesheet" href="<?php echo htmlspecialchars(AUTH_CSS); ?>">
<?php endif; ?>
</head>
<body>
<h1>Přihlášení</h1>
<h2><?php echo htmlspecialchars(PROJEKT_NAZEV); ?></h2>
<?php if (!empty($chyba)): ?>
<p><strong>Chyba: <?php echo htmlspecialchars($chyba); ?></strong></p>
<?php endif; ?>
<form method="POST" action="">
<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($csrf_token); ?>">
<p>
<label for="email">Email:</label><br>
<input
type="email"
id="email"
name="email"
value="<?php echo $email_hodnota; ?>"
required
autocomplete="email"
>
</p>
<p>
<label for="heslo">Heslo:</label><br>
<input
type="password"
id="heslo"
name="heslo"
required
autocomplete="current-password"
>
</p>
<p>
<label>
<input type="checkbox" name="zapamatovat" value="1">
Zapamatovat si mě
</label>
</p>
<p>
<button type="submit">Přihlásit se</button>
</p>
</form>
<?php if (REGISTRACE_OTEVRENA): ?>
<p><a href="<?php echo htmlspecialchars(AUTH_REGISTRACE_URL); ?>">Nemáš účet? Zaregistruj se.</a></p>
<?php endif; ?>
<p><a href="<?php echo htmlspecialchars(AUTH_RESET_URL); ?>">Zapomněl jsi heslo?</a></p>
</body>
</html>