5. diel - Ners - Registrácia užívateľov v PHP
V minulej lekcii, Programujeme neobjektové redakčný systém v PHP (Ners) , sme si pripravili projekt Ners - neobjektové Redakčný Systém v PHP a rozpracovali sme skript registrace.php.
Teraz 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(); } } } ?>
Ako prvý voláme session_start (). Funkcia nám umožní používať tzv. Session (slovensky relácie alebo niekedy aj sedenie), ktorá si pamätá dáta používateľa, s ktorým komunikujeme. Tento riadok musí byť na úplnom začiatku PHP súboru (nie bloku, naozaj súboru), v ktorom používateľskú relácii používame. Pred session_start () sa nesmie nachádzať žiadne HTML, ani prázdne riadky, ani medzery, inak nebude fungovať. To isté platí pre funkciu header ().
Ďalej načítame Db wrapper a pripojíme sa k databáze. Údaje sú pre localhost, vy už viete, že na produkciu vám ich oznámi webhosting.
Ďalšia kód je obsluha HTML formulára. Pokiaľ zadaný rok nesúhlasí s aktuálnym, uložíme si chybovú správu. Inak pokračujeme ďalej a rovnakým spôsobom overíme zhodu oboch zadaných hesiel. Dostávame sa k samotnej registrácii.
Najprv necháme databázu spočítať koľko je v nej používateľov so zadaným menom. Slúži na to SQL klauzula SELECT COUNT (*). Hviezdička označuje, že do výpočtu zahŕňame všetky stĺpce. Aby sme databázu zbytočne zaťažovali, dáme na počet položiek ešte LIMIT 1. Stačí nám, keď zistíme, že je v databáze nejaký užívateľ s týmto menom a ďalej sa už databázy snažiť nemusí. Otázka zavoláme funkcií Db :: querySingle (). Tá sa používa v prípade, keď z databázy čítame iba jednu hodnotu jedného riadku. My tu čítame iba jedno číslo - počet používateľov s týmto menom. Ak sme niekoho našli, meno je už obsadené a uložíme si chybovú hlášku.
SQL kód pre vloženie užívateľa do databázy je veľmi podobný tomu z
minulých lekcií. O niečo zložitejšie je tu ukladanie hesla. Heslo
nevložíte do databázy priamo a to preto, keby došlo k úniku dát, aby
útočník nezískal heslá používateľov. Použijeme tzv. Hashovacie funkciu
password_hash()
, ktorá z daného hesla vypočíta jeho odtlačok.
Najbezpečnejší spôsob uchovania hesla v databáze je totiž heslo vôbec
neuchová, ale uchovať si iba jeho hash. Hash je dlhý reťazec zdanlivo
nesúvisiacich znakov a číslic a nemožno z neho pôvodnej heslo zistiť.
Hashovacie funkcia je teda iba jednosmerná. Keď budeme chcieť zistiť, či
používateľ zadal správne heslo, jednoducho z neho znovu spočítame
odtlačok a porovnáme, či sa odtlačky hesiel zhodujú. K tomu následne
slúži funkcia password_verify()
, ktorej použitie uvidíte ďalej
v kurze.
Okrem výsledného hashe, odtlačku, je v návratovej hodnote
funkcie uložená aj informácie o použitom algoritmu. To umožňuje v
budúcnosti jednoduchý prechod na nové a bezpečnejšie algoritmy. Na rozdiel
od starších PHP funkciou hash()
alebo crypt()
,
password_hash()
automaticky k heslu pripája tiež tzv. Salt. To je
náhodný reťazec znakov, ktorým sa heslo "prisoľte", aby v databáze nešli
spoznať často používané heslá ako napr. "123456" alebo "heslo1" a
podobne.
Po vložení užívateľa do databázy si vytvoríme užívateľskú reláciu. V PHP je podobne ako $ _GET alebo $ _POST tiež superglobálnych poľa $ _SESSION. Do tohto poľa si môžeme ukladať dáta, ktoré súvisia s tým používateľom, s ktorým práve komunikujeme. Relácia vyprší v predvolenom nastavení PHP za 24 minút nečinnosti alebo po zatvorení prehliadača. Akonáhle ju raz vytvoríme v nejakom skriptu, zostanú nám jej dáta prístupné aj pre ostatných PHP skripty v aplikácii. My tu užívateľa po registrácii rovno aj prihlásime a to tak, že do relácie uložíme jeho id, meno a či je administrátor. Id (primárny kľúč) záznamu naposledy vloženého do databázy získame pomocou funkcie Db :: getLastId (). Nakoniec sa presmerujeme funkciou header () na stránku administrace.php a skript zastavíme. Ak sa niečo nepodarilo, skript bude pokračovať a vypíše chybovú hlášku.
Skúsme si urobiť nejakú chybu:
A teraz sa úspešne zaregistrovať. Skript vás prenesie na stránku administrace.php, ktorá ešte neexistuje. Pozrite sa v phpMyAdmin do tabuľky uzivatele (otvorte tabuľku a vyberte z menu hore Prejst). Vidíme tu novo vloženého užívateľa a odtlačok jeho hesla:
Ako heslo som zadal "admin", vyššie vidíte odtlačok, čo vrátila funkcia
password_hash()
.
Administrácia
Vytvorme si teraz skript administrace.php. Bude to taký rozcestník, na ktorý aplikácie užívateľa prenesie po zaregistrovaní alebo po prihlásení. Jeho HMTL časť bude nasledujúce:
<!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 iba 3 zaujímavé veci:
- Vypisujeme tu meno prihláseného užívateľa z relácie (session).
- Pokiaľ nie je prihlásený používateľ administrátor, informujeme ho o tom.
- Pre odhlásenie užívateľa odkážeme na skript administrace.php s GET parametrom 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ýsledok:
Ak session neexistuje, presmerujeme na prihlasovaciu stránku a zastavíme skript. Ak je zadaný parameter odhlásiť zničíme session pomocou PHP funkcie session_destroy () a opäť presmerujeme na prihlásenie.
Budeme pokračovať v budúcej lekcii, Ners - Editor článkov v PHP .