INF.03 · Aplikacje internetowe PHP
Rejestracja użytkownika (formularz, baza danych, hasło)
Rejestracja bez zapisywania hasła.
- PHP8.3
- mysqli · MariaDB
- Praktyka i diagnoza
Po tej lekcji: Utworzysz konto z unikalnym emailem i hashem hasła, rozumiejąc rolę walidacji oraz ograniczenia UNIQUE.
Zrozum mechanizm
Formularz wysyła email, hasło i powtórzenie przez POST. Serwer kontroluje CSRF, kształt danych, format emaila i politykę hasła. W tym projekcie email jest normalizowany do małych liter. Hasła nie przycinamy ani nie zmieniamy. Polityka ćwiczenia: co najmniej 15 znaków i maksymalnie 72 bajty UTF-8 — to świadome ograniczenie zgodności z bcrypt, nie limit 72 liter.
Password_hash z PASSWORD_DEFAULT generuje hash z losową solą; nie dopisuj własnej soli, nie używaj md 5 ani sha 256 jako zamiennika funkcji do haseł. Ten sam tekst zwykle daje różne hashe. Przechowuj wynik w VARCHAR(255), ponieważ domyślny algorytm może się zmienić. Hasła nie szyfrujemy do późniejszego odczytania.
INSERT jest parametryzowany. UNIQUE(email) rozstrzyga również wyścig dwóch rejestracji — wcześniejszy SELECT sam nie gwarantuje unikalności. Błąd 1062 obsługujemy bez wycieku SQL; odpowiedź nie rozróżnia jawnie istnienia adresu. Rejestracja w tym projekcie nie loguje automatycznie. Dodatkowe elementy publicznej aplikacji, np. potwierdzenie email i odzyskiwanie konta, są osobnym wdrożeniem.
Jak uruchamiać krótkie przykłady?
Każdy krótki przykład oznaczony własnym plikiem uruchamiaj osobno, nie doklejaj wszystkich definicji do jednego pliku. W edytorze zapisz go jako .php, a w terminalu tego folderu wpisz np. php for.php. Wtedy pokazane końce wierszy PHP_EOL są widoczne. W odpowiedzi HTML znak końca wiersza sam nie robi nowej linii na ekranie: użyj <br> albo znacznika <pre>. Wyświetl źródło pozwala zobaczyć tekst odpowiedzi.
Przykłady opisane jako fragment projektu wymagają paczki KINO / LAB i wcześniejszej konfiguracji. Nie uruchamiaj ich jako samodzielnych endpointów. Pełny plik niżej pokazuje kontekst. Funkcje h(), pole() i wymagajPost() są nasze; ich definicje wczytuje bootstrap.php.
Hasło: hash do zapisu, tekst tylko do sprawdzenia
Najpierw zobacz samą operację. To nie jest jeszcze rejestracja: cały formularz, walidacja, CSRF i INSERT są w pełnym pliku niżej.
Podstawowa forma: password_hash(haslo, PASSWORD_DEFAULT) → napis do bazy
<?php
$haslo = 'Fikcyjne haslo ucznia 2026';
$hash = password_hash($haslo, PASSWORD_DEFAULT);
echo password_verify($haslo, $hash) ? 'zgodne' : 'błędne';
zgodne
- password_hash bierze tekst hasła i nazwę algorytmu. PASSWORD_DEFAULT to stała PHP wybierająca domyślny algorytm, nie nazwa hasła.
- Funkcja tworzy napis zawierający informacje potrzebne do późniejszej weryfikacji. Ten napis zapisujesz do kolumny haslo_hash typu VARCHAR(255).
- password_verify bierze wpisane hasło i zapisany hash, zwraca bool. W przykładzie ?: zamienia true na napis zgodne.
- Losowa sól jest generowana automatycznie. Dwa wywołania hash dla tego samego tekstu mogą dać różne napisy; dlatego nie porównujemy nowego hasha ze starym operatorem ===.
Jak czytać pozostałe zapisy w pełnym przykładzie
| Zapis | Znaczenie | Przykład użycia |
|---|---|---|
pole($dane, $nazwa) | Nasza funkcja: pobiera wskazany klucz tylko wtedy, gdy ma wartość string; inaczej oddaje pusty napis. isset sprawdza obecność i brak null, is_string typ. | pole($_POST, "email") |
h($tekst) | Nasza funkcja kodująca tekst/atrybut HTML przez htmlspecialchars; nie wykonuje walidacji zakresu ani zabezpieczenia SQL. | h($film["tytul"]) |
wymagajPost() | Nasza funkcja: sprawdza metodę POST oraz CSRF; przy błędzie przerywa odpowiedź z405/403. | wymagajPost(); |
tokenFormularza() | Nasza funkcja zwraca HTML ukrytego pola csrf z wartością sesji zakodowaną przez h. | <?= tokenFormularza() ?> |
przekieruj($adres) | Nasza funkcja wysyła Location ze statusem303 i kończy wykonanie przez exit. Typ wyniku never oznacza, że nie wraca do dalszej instrukcji. | przekieruj("/panel.php"); |
naglowek($tytul), stopka() | Nasze funkcje wypisujące wspólny HTML strony. void oznacza brak zwracanego wyniku do użycia w wyrażeniu. | naglowek("Katalog"); |
dirname(__DIR__) | dirname daje katalog nadrzędny; __DIR__ to katalog bieżącego pliku. W public prowadzi to do katalogu projektu, a dopisana ścieżka wskazuje src. | dirname(__DIR__)."/src/bootstrap.php" |
try / catch / throw | try obejmuje próbę, catch przechwytuje wyjątek, throw go zgłasza; $blad jest obiektem błędu. W mysqli raportowanie wyjątków trzeba włączyć. | try { /* operacja */ } catch (Throwable $blad) { /* obsługa */ } |
===, !==, &&, ||, ! | Identyczne, nieidentyczne, i, lub, zaprzeczenie. Porównanie ścisłe obejmuje typ; &&/|| nie sprawdzają drugiej części, gdy wynik jest już rozstrzygnięty. | $rok === false || $rok < 1888 |
-> oraz :: | -> wybiera właściwość lub metodę obiektu; :: odnosi się do elementu statycznego klasy. To nie jest zapis dostępu do tablicy. | $zapytanie->execute(); |
Sprawdź w działaniu
Rejestracja bez zapisywania hasła — sprawdź w modelu
Model w przeglądarce wyjaśnia mechanizm na fikcyjnych danych. Nie wykonuje PHP ani zapytań SQL i nie tworzy kont. Prawdziwe skrypty uruchomisz lokalnie z paczki.
Przewidź rezultat, wykonaj próbę i wyjaśnij, która decyzja po stronie serwera decyduje o wyniku.
Uruchom krok po kroku
Załóż dwa fikcyjne konta z różnymi hasłami. Sprawdź niezgodne powtórzenie, błędny email, za krótkie hasło i powtórzony adres. W phpMyAdmin obejrzyj haslo_hash: nigdy jawne hasło. Nie oddawaj nauczycielowi użytego hasła, wartości cookie ani config.local.php. Do pracy dołącz opis testów i kod bez sekretów.
Plik wzorcowy: public/rejestracja.php
<?php
require_once dirname(__DIR__).'/src/db.php';
$komunikat = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
wymagajPost();
$email = mb_strtolower(trim(pole($_POST, 'email')));
$haslo = pole($_POST, 'haslo'); // Nie usuwaj spacji z hasła.
$powtorz = pole($_POST, 'powtorz');
if (strlen($email) > 254 || ! filter_var($email, FILTER_VALIDATE_EMAIL)
|| mb_strlen($haslo) < 15 || strlen($haslo) > 72 || $haslo !== $powtorz) {
http_response_code(422);
$komunikat = 'Sprawdź email oraz zgodność haseł: minimum 15 znaków i maksymalnie 72 bajty UTF-8.';
} else {
// PASSWORD_DEFAULT może zmienić algorytm. Kolumna ma zapas: VARCHAR(255).
$hash = password_hash($haslo, PASSWORD_DEFAULT);
$zapytanie = $polaczenie->prepare('INSERT INTO Uzytkownicy (email, haslo_hash) VALUES (?, ?)');
$zapytanie->bind_param('ss', $email, $hash);
try {
$zapytanie->execute();
} catch (mysqli_sql_exception $blad) {
// UNIQUE rozstrzyga również dwa równoczesne zgłoszenia.
if ($blad->getCode() !== 1062) {
throw $blad;
}
}
// Nie zdradzamy w odpowiedzi, czy adres był już zajęty.
przekieruj('/logowanie.php?rejestracja=1');
}
}
naglowek('Załóż konto do ćwiczeń');
?>
<p><?= h($komunikat) ?></p>
<form method="post" action="/rejestracja.php">
<?= tokenFormularza() ?>
<label for="email">Email fikcyjny</label><input id="email" name="email" type="email" maxlength="254" autocomplete="username" required>
<label for="haslo">Hasło: min. 15 znaków, maks. 72 bajty UTF-8</label><input id="haslo" name="haslo" type="password" autocomplete="new-password" required>
<label for="powtorz">Powtórz hasło</label><input id="powtorz" name="powtorz" type="password" autocomplete="new-password" required>
<button>Utwórz konto</button>
</form>
<?php stopka();
Co ma trafić do bazy?
W kolumnie haslo_hash znajduje się wynik password_hash, a nie oryginalny tekst. Dwa hashe tego samego hasła mogą być różne z powodu losowej soli. To poprawne. Password_verify odczytuje informacje z hasha i sprawdza hasło. Nigdy nie wypisuj hasła w odpowiedzi, logu, raporcie ani w SQL do oddania.
Pobierz i odtwórz projekt
W „Źródłach i materiałach” na końcu pobierz KINO / LAB.zip. Rozpakuj całość; instrukcja START.txt opisuje konfigurację. Pierwsze 6 przykładów w public/podstawy działa bez bazy. Dalsze wymagają lokalnej MariaDB 11.4, importu schema.sql i lokalnego konta bazy z minimalnymi prawami. Gotowa paczka pokazuje całość, ale w tej lekcji wykonaj opisane kroki i własne zadanie.
Ćwiczenie z pomocą · samodzielna praca
Twoja próba — podpowiedzi otwieraj po kolei
Wykonaj pięć prób rejestracji: poprawna, niepoprawny email, różne hasła, za krótkie hasło i duplikat.
Powstaje tylko jedno poprawne nowe konto; baza przechowuje hash; brak błędu 500 i surowego SQL.
? Potrzebujesz pomocy? Rozwiązuj krok po kroku.
Krok 1 — pokaż podpowiedź
Odszukaj wskazany plik i zapisz przewidywany rezultat przed zmianą.
Krok 2 — pokaż podpowiedź
Zmień jedną rzecz. Sprawdź metodę żądania, dane i odpowiedź lub wynik programu.
Krok 3 — pokaż podpowiedź
Wykonaj próbę graniczną lub błędną. Porównaj także stan bazy lub sesji, nie tylko komunikat.
Otwórz tylko tyle podpowiedzi, ile potrzebujesz. Po każdym kroku wróć do zadania i sprawdź wynik.
Podsumowanie
Co warto zapamiętać
- Utworzysz konto z unikalnym emailem i hashem hasła, rozumiejąc rolę walidacji oraz ograniczenia UNIQUE.
- Potrafisz wskazać w kodzie przyczynę wyniku i zaplanować próbę błędnych danych.
- Nie oddajesz haseł, pliku config.local.php ani wartości cookie.
Dalej na swoim koncie
Rozgrzewki, quiz i zadania są w biurku ucznia.
Teoria jest otwarta dla wszystkich. Żeby rozwiązywać zadania, zapisywać szkice i widzieć swój postęp, zaloguj się.
Zaloguj się →