Registracija uporabnika omogoča ustvarjanje novega računa v aplikaciji. Uporabnik vnese svoje podatke, aplikacija jih preveri, nato pa novega uporabnika shrani v podatkovno zbirko.
Registracija je varnostno občutljiv postopek, ker aplikacija obdeluje osebne podatke in geslo. Zato moramo podatke preveriti, geslo shraniti kot hash, preprečiti podvojena uporabniška imena in e-poštne naslove ter uporabniku prikazati jasna sporočila.
Pomni: Gesla pri registraciji nikoli ne shranimo v navadnem besedilu. Pred shranjevanjem uporabimo funkcijo password_hash(), pri prijavi pa geslo preverimo s funkcijo password_verify().
Pri registraciji moramo poleg oblike podatkov preveriti tudi, ali uporabniško ime ali e-poštni naslov že obstajata v tabeli users.
Vsebina strani
Osnovna pravila
Pri registraciji ustvarimo nov uporabniški račun. Ker podatki prihajajo iz obrazca, jih moramo obravnavati kot nezaupan vnos.
- Obrazec za registracijo naj uporablja metodo
POST. - Vsa obvezna polja morajo biti izpolnjena.
- E-poštni naslov preverimo s
FILTER_VALIDATE_EMAIL. - Geslo in ponovljeno geslo se morata ujemati.
- Geslo mora biti dovolj dolgo in primerno zahtevno.
- Uporabniško ime in e-poštni naslov morata biti enkratna.
- Geslo pred shranjevanjem pretvorimo v hash.
- Za delo z bazo uporabimo pripravljene stavke.
- Po uspešni registraciji uporabnika preusmerimo na potrditveno ali prijavno stran.
Pozor: Preverjanje enkratnosti uporabniškega imena v aplikacijski kodi ni dovolj, če tabela nima ustreznih omejitev. V tabeli users je priporočljivo uporabiti tudi enolični indeks za username in mail.
Registracija novega uporabnika
Pri registraciji uporabnik običajno izpolni obrazec z osnovnimi podatki, kot so ime, priimek, uporabniško ime, e-poštni naslov in geslo. Aplikacija nato preveri pravilnost vnesenih podatkov in ustvari nov uporabniški račun.
Osnovna sintaksa za vnos novega uporabnika v tabelo je:
INSERT INTO users (ime, priimek, username, mail, password)
VALUES (vrednost1, vrednost2, vrednost3, vrednost4, vrednost5);
Pri registraciji gesla ne shranjujemo v navadnem besedilu. Pred shranjevanjem ga pretvorimo v varen hash, ki ga kasneje pri prijavi preverjamo s funkcijo password_verify().
Pred vnosom novega uporabnika pogosto izvedemo še poizvedbo, s katero preverimo, ali uporabniško ime ali e-poštni naslov že obstajata:
SELECT id
FROM users
WHERE username = :username OR mail = :mail;
Pomni: Pri registraciji običajno najprej preverimo podatke, nato preverimo podvajanje uporabnika, šele nato izvedemo INSERT INTO.
Osnovni primer z mysqli
Spodnji zgled prikaže osnovno registracijo uporabnika z uporabo mysqli, validacije polj in varnega shranjevanja gesla.
<?php
session_start();
define('DB_SERVER', 'localhost');
define('DB_USER', 'uporabnik');
define('DB_PASS', 'skritoGeslo');
define('DB_NAME', 'knjiznica');
$connection = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
if (!$connection) {
die(
'Povezava s podatkovno zbirko ni vzpostavljena: ' .
mysqli_connect_error() .
' (' . mysqli_connect_errno() . ')'
);
}
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$ime = trim($_POST['ime'] ?? '');
$priimek = trim($_POST['priimek'] ?? '');
$username = trim($_POST['uid'] ?? '');
$email = trim($_POST['mail'] ?? '');
$password = $_POST['pwd'] ?? '';
$rePassword = $_POST['re-pwd'] ?? '';
if ($ime === '' || $priimek === '' || $username === '' || $email === '' || $password === '' || $rePassword === '') {
$error = 'Vsa polja morajo biti izpolnjena.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = 'E-poštni naslov ni veljaven.';
} elseif ($password !== $rePassword) {
$error = 'Gesli morata biti enaki.';
} elseif (mb_strlen($password) < 8) {
$error = 'Geslo mora imeti vsaj 8 znakov.';
} else {
$stmtCheck = mysqli_prepare(
$connection,
"SELECT id FROM users WHERE username = ? OR mail = ?"
);
mysqli_stmt_bind_param($stmtCheck, 'ss', $username, $email);
mysqli_stmt_execute($stmtCheck);
$resultCheck = mysqli_stmt_get_result($stmtCheck);
if (mysqli_fetch_assoc($resultCheck)) {
$error = 'Uporabniško ime ali e-pošta je že uporabljena.';
} else {
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
$stmtInsert = mysqli_prepare(
$connection,
"INSERT INTO users (ime, priimek, username, mail, password)
VALUES (?, ?, ?, ?, ?)"
);
mysqli_stmt_bind_param($stmtInsert, 'sssss', $ime, $priimek, $username, $email, $passwordHash);
if (mysqli_stmt_execute($stmtInsert)) {
$_SESSION['regIme'] = $ime;
$_SESSION['regPriimek'] = $priimek;
header('Location: 15_register_OK.php');
exit();
} else {
$error = 'Registracija trenutno ni mogoča.';
}
mysqli_stmt_close($stmtInsert);
}
mysqli_stmt_close($stmtCheck);
}
}
mysqli_close($connection);
?>
Pri mysqli sta uporabljeni dve pripravljeni poizvedbi. Prva preveri, ali uporabnik že obstaja, druga pa novega uporabnika shrani v tabelo users.
Osnovni primer s PDO
Tudi z vmesnikom PDO registracijo izvedemo s pripravljeno poizvedbo, preverjanjem enkratnosti uporabnika in shranjevanjem hashiranega gesla.
<?php
session_start();
$streznik = 'localhost';
$baza = 'knjiznica';
$uporabnik = 'uporabnik';
$geslo = 'skritoGeslo';
try {
$pdo = new PDO("mysql:host=$streznik;dbname=$baza;charset=utf8mb4", $uporabnik, $geslo);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$ime = trim($_POST['ime'] ?? '');
$priimek = trim($_POST['priimek'] ?? '');
$username = trim($_POST['uid'] ?? '');
$email = trim($_POST['mail'] ?? '');
$password = $_POST['pwd'] ?? '';
$rePassword = $_POST['re-pwd'] ?? '';
if ($ime === '' || $priimek === '' || $username === '' || $email === '' || $password === '' || $rePassword === '') {
$error = 'Vsa polja morajo biti izpolnjena.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = 'E-poštni naslov ni veljaven.';
} elseif ($password !== $rePassword) {
$error = 'Gesli morata biti enaki.';
} elseif (mb_strlen($password) < 8) {
$error = 'Geslo mora imeti vsaj 8 znakov.';
} else {
$stmt = $pdo->prepare(
"SELECT id FROM users WHERE username = :username OR mail = :mail"
);
$stmt->bindValue(':username', $username, PDO::PARAM_STR);
$stmt->bindValue(':mail', $email, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->fetch(PDO::FETCH_ASSOC)) {
$error = 'Uporabniško ime ali e-pošta je že uporabljena.';
} else {
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
$query = $pdo->prepare(
"INSERT INTO users (ime, priimek, username, mail, password)
VALUES (:ime, :priimek, :username, :mail, :password)"
);
$query->execute(array(
':ime' => $ime,
':priimek' => $priimek,
':username' => $username,
':mail' => $email,
':password' => $passwordHash
));
$_SESSION['regIme'] = $ime;
$_SESSION['regPriimek'] = $priimek;
header('Location: 15_register_OK.php');
exit();
}
}
}
}
catch (PDOException $e) {
$error = 'Registracija trenutno ni mogoča.';
}
?>
Pri PDO uporabimo poimenovane parametre, na primer :username, :mail in :password. Tak zapis je pregleden in primeren za obrazce z več polji.
Preverjanje podatkov pri registraciji
Pri registraciji moramo skrbno preveriti vse podatke, saj le tako preprečimo napačne vnose in podvojene uporabniške račune.
| Podatek | Preverjanje |
|---|---|
ime |
Polje naj bo izpolnjeno in naj vsebuje dovoljene znake. |
priimek |
Polje naj bo izpolnjeno in naj vsebuje dovoljene znake. |
username |
Uporabniško ime naj bo izpolnjeno, ustrezne oblike in enkratno. |
mail |
E-poštni naslov naj bo veljaven in enkraten. |
pwd |
Geslo naj bo dovolj dolgo in naj ne bo prazno. |
re-pwd |
Ponovljeno geslo se mora ujemati z geslom. |
Pozor: Validacija v brskalniku ni dovolj. Tudi če obrazec uporablja HTML preverjanje, mora strežniška PHP koda ponovno preveriti vse prejete podatke.
Varno shranjevanje gesla
Geslo pred shranjevanjem pretvorimo v hash. Za to uporabimo funkcijo password_hash(). Pri sodobnem PHP je priporočljivo uporabiti PASSWORD_DEFAULT, saj PHP sam izbere primeren algoritem.
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
Pri prijavi nato uporabimo funkcijo password_verify():
if (password_verify($passwordAttempt, $user['password'])) {
// geslo je pravilno
}
Hash gesla shranimo v stolpec password v tabeli users.
Pomni: Hash ni enako kot šifriranje. Pri pravilnem shranjevanju gesel ne potrebujemo pridobiti izvirnega gesla nazaj, ampak samo preveriti, ali se vneseno geslo ujema s shranjenim hashom.
Potrditev uspešne registracije
Po uspešni registraciji uporabnika pogosto preusmerimo na potrditveno stran. Tam lahko prikažemo prijazno obvestilo in povezavo na prijavo.
$_SESSION['regIme'] = $ime;
$_SESSION['regPriimek'] = $priimek;
header('Location: 15_register_OK.php');
exit();
Podatkov, kot je geslo, nikoli ne shranjujemo v sejo za prikaz potrditve.
Pozor: Pred uporabo funkcije header() ne sme biti izpisa v brskalnik. Po preusmeritvi uporabimo exit(), da ustavimo nadaljnje izvajanje skripte.
Primerjava pristopov mysqli in PDO
Oba pristopa omogočata varno registracijo s pripravljenimi stavki. Razlika je predvsem v zapisu poizvedb, vezavi parametrov in obravnavi napak.
| Korak | mysqli |
PDO |
|---|---|---|
| Preverjanje obstoječega uporabnika | mysqli_prepare() in mysqli_stmt_bind_param() |
$pdo->prepare() in bindValue() |
| Vnos novega uporabnika | INSERT INTO users s parametri ? |
INSERT INTO users s poimenovanimi parametri |
| Hashiranje gesla | password_hash() |
password_hash() |
| Branje rezultata preverjanja | mysqli_fetch_assoc() |
$stmt->fetch() |
| Preusmeritev | header() in exit() |
header() in exit() |
Aplikacija Knjige
📘Aplikacija Knjige
V priloženi aplikaciji je registracija izvedena v datoteki 15_register.php. Ob oddaji obrazca aplikacija prebere ime, priimek, uporabniško ime, e-pošto in obe gesli, nato pa preveri pravilnost vseh polj. Posebej preveri veljavnost e-pošte, dovoljene znake v imenu, priimku in uporabniškem imenu, enakost obeh gesel ter minimalno dolžino gesla.
Nato s pripravljeno poizvedbo PDO preveri, ali uporabniško ime oziroma ali e-poštni naslov že obstaja v tabeli users. Če uporabnik še ne obstaja, aplikacija geslo pretvori v varen hash z password_hash() in novega uporabnika shrani v bazo.
Po uspešni registraciji aplikacija v sejo shrani ime in priimek, nato pa uporabnika preusmeri na stran 15_register_OK.php, kjer se izpiše potrditveno sporočilo in povezava na prijavo.
15_register.php15_register_OK.phpNavodila za izdelavo registracije
- Najprej pripravimo obrazec za vnos podatkov novega uporabnika.
- Ob oddaji obrazca preberemo vsa polja.
- Preverimo, ali so polja pravilno izpolnjena.
- Preverimo veljavnost e-poštnega naslova.
- Preverimo, ali se geslo in ponovljeno geslo ujemata.
- V bazi preverimo, ali uporabniško ime oziroma ali e-pošta že obstaja.
- Geslo pretvorimo v hash s funkcijo password_hash().
- Novega uporabnika shranimo v tabelo
users. - Po uspešni registraciji uporabnika preusmerimo na potrditveno ali prijavno stran.
Pozor: Če uporabniško ime ali e-pošta že obstajata, novega uporabnika ne vnesemo v tabelo. Najprej prikažemo sporočilo in uporabniku omogočimo popravek podatkov.
Priporočila
- Vsa polja preveri na strežniku.
- Za e-poštni naslov uporabi
FILTER_VALIDATE_EMAIL. - Uporabniško ime in e-pošto preveri pred vnosom.
- Geslo shrani samo kot rezultat funkcije
password_hash(). - Za vnos uporabnika uporabi pripravljen stavek.
- Za
usernameinmailuporabi enolične omejitve v tabeliusers. - Po uspešni registraciji ne prikazuj gesla ali hasha.
- Po preusmeritvi uporabi
exit().
Pogoste napake
- Geslo se shrani v navadnem besedilu.
- Geslo se prikaže na potrditveni strani.
- Obe gesli se ne primerjata pred vnosom.
- E-poštni naslov ni preverjen.
- Uporabniško ime ali e-pošta nista preverjena glede podvajanja.
- Vnos uporabnika ni izveden s pripravljenim stavkom.
- V tabeli
usersni enoličnih omejitev zausernameinmail. - Po klicu
header()manjkaexit().
Registracija mora biti zasnovana tako, da varuje podatke uporabnika in podatkovno bazo. Najpomembnejši deli so preverjanje podatkov, pripravljene poizvedbe, enkratnost uporabnika in varno shranjevanje gesla.