Lekce 5 - NERS - Registrace uživatelů v PHP
V minulé lekci, Programujeme neobjektový redakční systém v PHP (NERS), jsme dokončili jednoduchou aplikaci k registraci a výpisu uživatelů.
Nyní nad HTML blok vložíme blok s PHP obsluhou:
<?php session_start(); require('Db.php'); Db::connect('127.0.0.1', 'ners_db', 'root', ''); if ($_POST) { if ($_POST['rok'] != date('Y')) $zprava = 'Chybně vyplněný antispam.'; else if ($_POST['heslo'] != $_POST['heslo_znovu']) $zprava = 'Hesla nesouhlasí'; else { $existuje = Db::querySingle(' SELECT COUNT(*) FROM uzivatele WHERE jmeno=? LIMIT 1 ', $_POST['jmeno']); if ($existuje) $zprava = 'Uživatel s touto přezdívkou je již v databázi obsažen.'; else { $heslo = password_hash($_POST['heslo'], PASSWORD_DEFAULT); Db::query(' INSERT INTO uzivatele (jmeno, heslo) VALUES (?, ?) ', $_POST['jmeno'], $heslo); $_SESSION['uzivatel_id'] = Db::getLastId(); $_SESSION['uzivatel_jmeno'] = $_POST['jmeno']; $_SESSION['uzivatel_admin'] = 0; header('Location: administrace.php'); exit(); } } } ?>
Jako první voláme session_start(). Funkce nám umožní používat tzv. session (česky relace nebo někdy i sezení), která si pamatuje data uživatele, se kterým komunikujeme. Tento řádek musí být na úplném začátku PHP souboru (ne bloku, opravdu souboru), ve kterém uživatelskou relaci používáme. Před session_start() se nesmí nalézat žádné HTML, ani prázdné řádky, ani mezery, jinak nebude fungovat. To samé platí pro funkci header().
Dále načteme Db wrapper a připojíme se k databázi. Údaje jsou pro localhost, vy již víte, že na produkci vám je sdělí webhosting.
Další kód je obsluha HTML formuláře. Pokud zadaný rok nesouhlasí s aktuálním, uložíme si chybovou zprávu. Jinak pokračujeme dále a stejným způsobem ověříme shodu obou zadaných hesel. Dostáváme se k samotné registraci.
Nejprve necháme databázi spočítat kolik je v ní uživatelů se zadaným jménem. Slouží k tomu SQL klauzule SELECT COUNT(*). Hvězdička označuje, že do výpočtu zahrnujeme všechny sloupce. Abychom databázi zbytečně zatěžovali, dáme na počet položek ještě LIMIT 1. Stačí nám, když zjistíme, že je v databázi nějaký uživatel s tímto jménem a dále se již databáze snažit nemusí. Dotaz zavoláme funkcí Db::querySingle(). Ta se používá v případě, když z databáze čteme pouze jednu hodnotu jednoho řádku. My zde čteme pouze jedno číslo - počet uživatelů s tímto jménem. Pokud jsme někoho našli, jméno je již obsazené a uložíme si chybovou hlášku.
SQL kód pro vložení uživatele do databáze je velmi podobný tomu z
minulých lekcí. O něco složitější je zde ukládání hesla. Heslo
nevložíme do databáze přímo a to proto, kdyby došlo k úniku dat, aby
útočník nezískal hesla uživatelů. Použijeme tzv. hashovací funkci
password_hash()
, která z daného hesla vypočítá jeho otisk.
Nejbezpečnější způsob uchování hesla v databázi je totiž heslo vůbec
neuchovat, ale uchovat si pouze jeho hash. Hash je dlouhý řetězec zdánlivě
nesouvisejících znaků a číslic a nelze z něj původní heslo zjistit.
Hashovací funkce je tedy pouze jednosměrná. Když budeme chtít zjistit, zda
uživatel zadal správné heslo, jednoduše z něj znovu spočítáme otisk a
porovnáme, zda se otisky hesel shodují. K tomu následně slouží funkce
password_verify()
, jejíž použití uvidíte dále v kurzu.
Kromě výsledného hashe, otisku, je v návratové hodnotě
funkce uložena také informace o použitém algoritmu. To umožňuje v budoucnu
snadný přechod na nové a bezpečnější algoritmy. Na rozdíl od starších
PHP funkcí hash()
nebo crypt()
,
password_hash()
automaticky k heslu připojuje také tzv. salt. To
je náhodný řetězec znaků, kterým se heslo "přisolí", aby v databázi
nešly poznat často používaná hesla jako např. "123456" nebo "heslo1" a
podobně.
Po vložení uživatele do databáze si vytvoříme uživatelskou relaci. V PHP je podobně jako $_GET nebo $_POST také superglobální pole $_SESSION. Do tohoto pole si můžeme ukládat data, které souvisí s tím uživatelem, se kterým právě komunikujeme. Relace vyprší ve výchozím nastavení PHP za 24 minut nečinnosti nebo po zavření prohlížeče. Jakmile ji jednou vytvoříme v nějakém skriptu, zůstanou nám její data přístupná i pro ostatní PHP skripty v aplikaci. My zde uživatele po registraci rovnou i přihlásíme a to tak, že do relace uložíme jeho id, jméno a zda je administrátor. Id (primární klíč) záznamu naposledy vloženého do databáze získáme pomocí funkce Db::getLastId(). Nakonec se přesměrujeme funkcí header() na stránku administrace.php a skript zastavíme. Pokud se něco nepodařilo, skript bude pokračovat a vypíše chybovou hlášku.
Zkusme si udělat nějakou chybu:

A nyní se úspěšně zaregistrujte. Skript vás přenese na stránku administrace.php, která ještě neexistuje. Podívejte se v phpMyAdmin do tabulky uzivatele (otevřete tabulku a vyberte z menu nahoře Projít). Vidíme zde nově vloženého uživatele a otisk jeho hesla:

Jako heslo jsem zadal "admin", výše vidíte otisk, co vrátila funkce
password_hash()
.
Administrace
Vytvořme si nyní skript administrace.php. Bude to takový rozcestník, na který aplikace uživatele přenese po zaregistrování nebo po přihlášení. Jeho HMTL část bude následující:
<!DOCTYPE html> <html lang="cs-cz"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="styl.css" type="text/css" /> <title>Administrace</title> </head> <body> <article> <div id="centrovac"> <header> <h1>Administrace</h1> </header> <section> <p>Vítejte v administraci, jste přihlášeni jako <?= htmlspecialchars($_SESSION['uzivatel_jmeno']) ?></p> <?php if (!$_SESSION['uzivatel_admin']) echo('Nemáte administrátorská oprávnění, požádejte administrátora webu, aby vám je přidělil.'); ?> <h2><a href="editor.php">Editor článků</a></h2> <h2><a href="clanky.php">Seznam článků</a></h2> <h2><a href="administrace.php?odhlasit">Odhlásit</a></h2> </section> <div class="cistic"></div> </div> </article> </body> </html>
Kód obsahuje pouze 3 zajímavé věci:
- Vypisujeme zde jméno přihlášeného uživatele z relace (session).
- Pokud není přihlášený uživatel administrátor, informujeme ho o tom.
- Pro odhlášení uživatele odkážeme na skript administrace.php s GET parametrem odhlasit.
Nad kód vložíme jednoduchý PHP blok:
<?php session_start(); if (!isset($_SESSION['uzivatel_id'])) { header('Location: prihlaseni.php'); exit(); } if (isset($_GET['odhlasit'])) { session_destroy(); header('Location: prihlaseni.php'); exit(); } ?>
Výsledek:

Pokud session neexistuje, přesměrujeme na přihlašovací stránku a zastavíme skript. Pokud je zadaný parametr odhlasit, zničíme session pomocí PHP funkce session_destroy() a opět přesměrujeme na přihlášení.
V další lekci, NERS - Editor článků v PHP, využijeme editor TinyMCE.
Komentáře


Zobrazeno 10 zpráv z 136. Zobrazit vše