Logowanie użytkowników i ochrona podstron
- Użytkownicy i logowanie
- poziom: średni
- aktualizacja: 12 lipca 2026
Ten skrypt uzupełnia rejestrację o logowanie oparte na sesjach. Zawiera wszystko, co niezbędne: weryfikację hasła, zabezpieczenie przed przejęciem sesji (odnowienie jej identyfikatora po zalogowaniu), spowolnienie ataków siłowych, wylogowanie i gotową funkcję do ochrony dowolnej podstrony.
PHP
136 linii
Pobierz .php
<?php
/**
* Logowanie użytkowników — skryptyPHP.com
* Zapisz jako: logowanie.php
* Wymaga tabeli `uzytkownicy` ze skryptu „Rejestracja użytkowników".
*/
session_start();
require 'baza.php'; // skrypt „Połączenie z bazą (PDO)"
// ── FUNKCJE — możesz je przenieść do wspólnego pliku auth.php ──
function czy_zalogowany(): bool
{
return isset($_SESSION['uzytkownik_id']);
}
/**
* Wstaw na początku każdej chronionej podstrony:
* require 'auth.php';
* wymagaj_logowania();
*/
function wymagaj_logowania(): void
{
if (!czy_zalogowany()) {
header('Location: logowanie.php');
exit;
}
}
function wyloguj(): 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();
}
// ── WYLOGOWANIE ─────────────────────────────────────────────
if (($_GET['akcja'] ?? '') === 'wyloguj') {
wyloguj();
header('Location: logowanie.php');
exit;
}
// ── LOGOWANIE ───────────────────────────────────────────────
$blad = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = mb_strtolower(trim($_POST['email'] ?? ''));
$haslo = $_POST['haslo'] ?? '';
// Hamulec dla ataków siłowych: rosnące opóźnienie po błędnych próbach
$proby = $_SESSION['nieudane_proby'] ?? 0;
if ($proby > 2) {
sleep(min($proby - 2, 5));
}
$pdo = polacz_z_baza();
$stmt = $pdo->prepare(
'SELECT id, imie, haslo_hash FROM uzytkownicy WHERE email = ?'
);
$stmt->execute([$email]);
$uzytkownik = $stmt->fetch();
if ($uzytkownik && password_verify($haslo, $uzytkownik['haslo_hash'])) {
// Nowy identyfikator sesji — ochrona przed tzw. session fixation
session_regenerate_id(true);
$_SESSION['uzytkownik_id'] = (int) $uzytkownik['id'];
$_SESSION['uzytkownik_imie'] = $uzytkownik['imie'];
unset($_SESSION['nieudane_proby']);
// Okazja do bezkosztowego wzmocnienia starych haszy
if (password_needs_rehash($uzytkownik['haslo_hash'], PASSWORD_DEFAULT)) {
$nowy = password_hash($haslo, PASSWORD_DEFAULT);
$pdo->prepare('UPDATE uzytkownicy SET haslo_hash = ? WHERE id = ?')
->execute([$nowy, $uzytkownik['id']]);
}
header('Location: panel.php'); // dokąd po zalogowaniu
exit;
}
$_SESSION['nieudane_proby'] = $proby + 1;
// Jeden komunikat dla obu przypadków — nie zdradzamy, czy konto istnieje
$blad = 'Nieprawidłowy e-mail lub hasło.';
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Logowanie</title>
<style>
.formularz { max-width: 380px; font-family: sans-serif; margin: 20px auto; }
.formularz label { display: block; margin: 12px 0 4px; font-weight: bold; }
.formularz input { width: 100%; padding: 8px; box-sizing: border-box; }
.formularz button { margin-top: 16px; padding: 10px 24px; cursor: pointer; }
.blad { color: #b00020; }
</style>
</head>
<body>
<form class="formularz" method="post" action="">
<h2>Zaloguj się</h2>
<?php if (czy_zalogowany()): ?>
<p>Jesteś już zalogowany jako
<strong><?= htmlspecialchars($_SESSION['uzytkownik_imie']) ?></strong>.
<a href="?akcja=wyloguj">Wyloguj się</a></p>
<?php endif; ?>
<?php if ($blad): ?>
<p class="blad"><?= htmlspecialchars($blad) ?></p>
<?php endif; ?>
<label for="email">E-mail</label>
<input type="email" id="email" name="email" required>
<label for="haslo">Hasło</label>
<input type="password" id="haslo" name="haslo" required
autocomplete="current-password">
<button type="submit">Zaloguj się</button>
<p><a href="rejestracja.php">Nie masz konta? Zarejestruj się</a></p>
</form>
</body>
</html>
Jak użyć tego skryptu
- Skorzystaj najpierw ze skryptu „Rejestracja użytkowników" — logowanie używa tej samej tabeli
uzytkownicy. - Zapisz kod jako
logowanie.phpi zmień w nim adres przekierowania po zalogowaniu (panel.php). - Aby zabezpieczyć podstronę, przenieś funkcje do pliku
auth.phpi na początku chronionej strony wywołajsession_start(),require 'auth.php'orazwymagaj_logowania();. - Link wylogowania:
logowanie.php?akcja=wyloguj.
Warto wiedzieć
password_verify()porównuje hasło z haszem w stałym czasie — nie porównuj haszy operatorem==.session_regenerate_id(true)po zalogowaniu to ważny detal — unieważnia identyfikator sesji sprzed logowania.- Komunikat błędu celowo nie mówi, czy istnieje konto z podanym e-mailem — to utrudnia zgadywanie loginów.
- Na stronie z HTTPS (dziś standard) dodaj w PHP
ini_set('session.cookie_secure', '1')orazsession.cookie_httponly = 1, aby ciasteczko sesyjne nie wyciekło.
#logowanie
#sesje
#password_verify
#auth
#bezpieczeństwo
Podobne skrypty
Użytkownicy i logowanie
Rejestracja użytkowników z password_hash()
Bezpieczna rejestracja kont: walidacja danych, sprawdzenie unikalności e-maila, haszowanie hasła funkcją password_hash() i zapis do bazy przez PDO.
średni Zobacz kod → Użytkownicy i logowanieResetowanie hasła przez e-mail (tokeny)
Pełna procedura „zapomniałem hasła": jednorazowy token z random_bytes(), w bazie tylko jego hasz, link ważny godzinę i formularz ustawiania nowego hasła.
zaawansowany Zobacz kod →