Mechanizmus byl navrhnut s cílem poskytnout co nejjednodušší, ale plně použitelný kód, který by bylo velmi snadné implementovat. Ke své činnosti potřebuje tabulku users, ve které bude přihlašovací jméno uloženo ve sloupci nick a heslo v password. Pro jednoduchost se hesla ukládají do databáze v otevřené podobě, ovšem dopsat kódování některou hashovací funkcí je velmi jednoduché.
Skript poskytuje několik funkcí najednou. Pokud jsou zjištěny neprázdné proměnné z logovacího formuláře, systém se pokusí uživatele přihlásit. Dále je v kódu vidět důležitá funkce, která má na starosti generování autorizačních řetězců a poslední část prování klasickou kontrolu stávajícího spojení, tj. zda se někdo nepokusil session ukrást.
Kód umožňuje jak fixaci spojení na jednu IP adresu, tak možnost vypršení platnosti po určitém časovém limitu. Bezpečnost těchto funkcí je zajištěna tajností proměnné $SecretCode. Při jeho zkompromitování může útočník při znalosti hesla vytvářet autorizační řetězce k jakékoliv IP adrese a jakémukoliv času.
Přistupme nyní k vlastnímu zdrojovému kódu.
// nejprve je potreba se pripojit do databaze
include "connect.php";
$SecretCode="thisisthecode";
// Generovani autorizacniho retezce
function AuthString($login, $password, $time=0) {
global $REMOTE_ADDR;
global $HTTP_USER_AGENT;
global $SecretCode;
// platnost session mozne nastavit k*10min
if ($time==0) $time=round(time()/(60*10));
return MD5( $login . $password . $REMOTE_ADDR .
$HTTP_USER_AGENT . $SecretCode . $time);
}
První řádky představují inicializaci. V souboru connect.php se provede připojení k databázi, dále se nastaví tajný řetězec, který si pochopitelně při vlastní implementaci změňte. Následuje funkce, která v závislosti na jménu, heslu a časovém údaji vrací autorizační řetězec. Ten se spočítá jako výsledek jednocestné hashovací funkce několika spojených řetězců. $REMOTE_ADDR vrací klientovu IP, $HTTP_USER_AGENT informace o prohlížeči a operačním systému (proč je nezahrnout..., bude to o něco bezpečnější).
Časový údaj se bere v sekundách od půlnoci 1. 1. 1970, tento údaj se ale dělí hodnotou 600 (tj. 10 min) a zaokrouhluje. Časový limit funguje tak, že se při kontrole platnosti řetězce testují tří vypočtené: jeden pro aktuální čas a posledních 10 minut, jeden pro interval před 10ti-20ti minutami a jeden pro čas od 20ti minut zpět do půl hodiny. Tím lze délku limitu nastavit.
if ((@$LogNick!="") && (@$LogPassword!="")) { // Prihlaseni
// Vynulujeme promenne aplikace
$Nick="";
$AuthString="";
// Zkusime se nalogovat
@$GetUser = MySQL_Query("SELECT * FROM users WHERE nick LIKE '".AddSlashes($LogNick)."'");
$User = MySQL_Fetch_Array($GetUser);
// Uspech?
if ($User["Password"]==$LogPassword) :
$Nick=$LogNick;
$AuthString=AuthString($LogNick,$LogPassword);
else:
echo "Log FAILED.";
endif;
// Posleme login name a autoritzacni retezec
SetCookie("Nick",$LogNick);
SetCookie("AuthString",$AuthString);
}
Pokud jsou nenulové proměnné, ve kterých se předpokládají údaje z formuláře ($LogNick a $LogPassword) systém se pokusí nalogovat. Následuje kontrola aktuálního autorizačního řetězce, která se provádí vždy (v předchozím případě by bylo možno ji vynechat, ale tímto se nic nepokazí).
// Testovani aktualniho nalogovani
if ((@$Nick!="") && (@$AuthString!="")) {
@$GetUser = MySQL_Query("SELECT * FROM users WHERE nick LIKE '".AddSlashes($Nick)."'");
$User=MySQL_Fetch_Array($GetUser);
//ted otestujeme cas. limit na max 3*10 min
if ( (AuthString($Nick, $User["password"])==@$AuthString) ||
(AuthString($Nick, $User["password"],round(time()/(60*10))-1)==@$AuthString) ||
(AuthString($Nick, $User["password"],round(time()/(60*10))-2)==@$AuthString) ):
// vse ok, posleme autorizacni retezec s novou casovou znamkou
$AuthString=AuthString($Nick,$User["password"]);
SetCookie("AuthString",$AuthString);
echo $AuthString;
else:
SetCookie("Nick","");
SetCookie("AuthString","");
Header("Location: login.php");
Die();
endif;
}
else //neni k dispozici autorizacni retezec
{
Header("Location: login.php");
Die();
}
Zbývá dodat, že jelikož je vše v jednom souboru, je možné se z logovacího formuláře odkazovat ihed na první stránku aplikace. Pokud je skript správně vložen ještě před jakýkoliv výstup (musí být-jinak by se neposlaly cookies), provede se nalogování samo.
Další vychytávky si necháme na příště. Knihovnu si můžete sáhnout
zde.