Autorizace uživatelů v PHP
Programujete-li web a chcete, aby se uživatelé
přihlašovali pod svým jménem a heslem, potřebujete při vstupu na
stránky (kromě úvodní logovací) mít jistotu, že skutečně přistupuje
ten uživatel, za kterého se vydává.
Způsobů, jak toho docílit je hned několik.
Předávat heslo v adrese samozřejmě nelze, stejně jako nelze předávat
pouze samostatné ID uživatele (kdokoli by si mohl zadat cizí ID, a
tak se podívat na cizí účet). Já zde popisuji jeden ze způsobů,
který lze použít již v PHP3. Jedná se o řešení předáváním
zahashované kombinace uživatelského hesla a náhodného klíče.
Ochrana přístupu
Ochrana přístupu uživatele je v popisovaném
řešení zajištěna třemi základními vlastnostmi:
- není předáváno jméno ani heslo uživatele
- předávaný autorizační klíč je dostatečně dlouhý, aby se nedal
zapamatovat pohledem
- autorizační klíč se mění při každém přechodu ze stránky na
stránku, tedy v momentě jeho zobrazení v poli adresy je již
neplatný
Nyní se podívejme, jak se těchto vlastností
dosáhne.
Princip řešení
Při přihlášení a úspěšné autorizaci uživatele
pomocí jména a hesla na úvodní stránce je vygenerován náhodný klíč
(nemusí být nijak dlouhý). Tento klíč se uloží do databáze uživatele
(stačí klasický sloupec typu INT - v MySQL). Následně je kombinace
hesla a vygenerovaného klíče zahashována do dlouhého těžko
zapamatovatelného řetězce - kódu, který se předává následujícím
stránkám v adrese jako proměnná.
Při vstupu na další stránku se z databáze
přečte heslo a kód odpovídající uživateli s daným ID. Pomocí stejné
hashovací funkce se zjistí správný kód a ten se porovná s kódem
předaným v adrese. Jestliže jsou stejné, je uživatel kladně ověřen.
Dále se vygeneruje nový náhodný klíč, opět uloží do databáze a znovu
zahashuje s heslem.
Zahashování znamená jednoznačné zakódování na
číslo, popř. řetězec pomocí nějaké funkce. Přitom se předpokládá, že
dobrá hashovací funkce bude přiřazovat výsledky rovnoměrně do oboru
hodnot, i když vstupní hodnoty rovnoměrně zadávány nebudou. Tedy i
pro velmi podobné vstupy funkce vrátí velmi nepodobné hodnoty.
Implementace řešení
Pro implementaci tohoto zabezpečení jsem použil
databázi MySQL a předpokládám, že mám tabulku UZIVATELE se sloupci
ID, KLIC typu INT.
Jako hashovací funkci jsem použil funkci md5,
která je standardní součástí PHP (oddíl Strings). Tato funkce kóduje
(hashuje) řetězec na řetězec na základě algoritmu Message-Digest. Ke
spojení hesla a kódu je použita klasická konkatenace (spojení)
řetězců. Ukázka činnosti funkce md5 je zde:
md5("heslo") =
"955db0b81ef1989b4a4dfeae8061a9a6" md5("veslo") =
"4bf643bf3816722ac9cbed5b6bb6c3c6" md5("veslo2") =
"db70577ce6a3772f22170f2a6cd8d171"
Takto vypadá funkce, která vygeneruje klíč,
uloží jej do databáze a vrátí kód:
function novy_kod($id)
{ //
Vygenerování klíče $klic =
rand(0,9999);
// Uložení
klíče mysql_query("UPDATE
UZIVATELE SET KLIC=\"$klic\" WHERE
ID=\"$id\";");
// Vygenerování
kódu list($heslo) =
mysql_fetch_row( mysql_query("SELECT HESLO FROM
UZIVATELE WHERE ID=\"$id\";")
); $kod =
md5($heslo.$klic);
return
$kod; } | |
Následující funkce provádí autorizaci uživatele
a vrací úspěšnost:
function
Autorizace($kod, $id) { // Načtení hesla a klíče z
databáze list($db_heslo,
$db_klic) = mysql_fetch_row( mysql_query("SELECT HESLO,
KLIC FROM UZIVATELE WHERE ID=\"$id\";")
);
//
Vygenerování
kódu $spravny_kod =
md5($db_heslo.$db_klic);
// Test správnosti
kódu return ($spravny_kod ==
$kod); } | |
Na svých stránkách pak už jen voláte funkci
Autorizace a v případě úspěchu vygenerujte nový klíč. Ukázka stránky
pak může vypadat následovně:
<? if
(!Autorizace($kod, $id))
{ Header("Location:
chyba.php"); exit; } $kod
= novy_kod($id); ?> <a
href="jinastranka.php?id=<?echo
$id?>&kod=<?echo $kod?>">Jiná
stránka</a>
| |
Tyto ukázky jsou pouze ilustrační a chybí v
nich ošetření databázových chyb.
Uvědomte si, že heslo není nikde posíláno mezi
serverem a klientem (samozřejmě kromě úvodního zalogování) a veškerá
práce s ním neopustí server. Přesto je vždy ověřeno, že se jedná o
téhož uživatele jako minule. Dále je také třeba si uvědomit, že když
se uživatel pokusí přihlásit ze svou různých míst (stačí 2 okna
prohlížeče na stejném počítači), první session skončí chybou.
Jiná řešení
Další možná řešení problému, která se v praxi
používají, je uchováváni IP adresy, ze které se uživatel přihlásí, a
její expirace po jisté době nečinnosti (např. 30 min). V PHP4 máte
navíc možnost použít tzv. sessions, které umožňují uchovávat hodnoty
proměnných v průběhu několika HTTP volání (request) aniž by byly
předávány v adrese stránky.
| Zaujal vás článek?
Pošlete nám přes toto rozhraní dobrovolný příspěvek
formou mikroplatby v systému I LIKE Q (vlevo - Q) anebo
v DirectPay (vpravo - kredity). |
|
Jiří Semecký - Další články
autora
|