neděle 21. ledna 2007

PHP Sessions

Na co to je?
Uvedu příklad: potřebuju předat proměnnou skriptu, použiju POST nebo GET, jak je libo. Například <a href="index.html?promenna=hodnota">Go</a> a je to.
Příklad druhý: potřebuju předat několik proměnných a to jak při přechodu na další stránku, tak i na následující stránku a další a další ... Můžu použít postup z příkladu č. 1 a nebo použiju session a v ušetřeném čase si můžu okusovat nechty na nohách.

Jak na to?
Dost důležitý je mít session zapnutý tzn. podívat se do php.conf a zapnout to. Mám ale pocit, že to implicitně zapnutý je.
Chci teď vytvořit skript (auth.php), který budu includovat do každé stránky a bude zajišťovat autorizaci uživatele. Ten bude vypadat asi takto:
<?

// Spustení session
session_start();

// Odhlaseni uzivatele
if ($_GET['akce'] == "odhlasit")
{
session_destroy();

echo "Byl jste odhlášen ze systému.<br>\n";

exit; // Provadeni skriptu se prerusi
}

/* Pokud byly predany promenne z formulare, ulozi se do
* session
*/
if (isset($_POST['formLogin']) OR isset($_POST['formHeslo']))
{
$_SESSION['login'] = $_POST['formLogin'];
$_SESSION['heslo'] = $_POST['formHeslo'];
}

// Ochrana proti SQL Injection
if (isset($_SESSION['login ']) AND (!ctype_alnum($_SESSION['login'])
OR !ctype_alnum($_SESSION['heslo'])))

echo "Jméno, nebo heslo obsahuje nepovolené znaky!";

exit;
{
// Pokud je zadáno jméno, nebo heslo, porovná se s databází
if (isset($_SESSION['login']) AND isset($_SESSION['heslo']))
{
$error = mysql_query("SELECT 1
FROM users
WHERE login = '".$_SESSION['login']."'
AND heslo = '".$_SESSION['heslo']."'
", $spojeni);
}

/* Pokud je heslo špatné => prázdný výpis z databáze, vypíše
* se formulář a ukončí skript
*/
if ($error == "")
{ // Nebylo-li jmeno nebo heslo, predane formularem spravne
if (isset($_POST['formLogin']) OR isset($_POST['formHeslo']))
{
echo "Špatné jméno, nebo heslo.<br>";
}

?>

<p>Nejste prihlášen do systému.</p>

<form action="<? echo $_SERVER['PHP_SELF'];
?>" method="post">
Login: <input type="text" name="formLogin"
value="<?php echo $_POST['login']; ?>"><br>
Heslo: <input type="password" name="formHeslo"><br>
<input type="submit" value="Přihlásit">
</form>

</body>
</html>
<?

exit;
}

/* Heslo musi byt v tomto miste spravne, pokracuje se ve
* skriptu
*/
if (isset($_SESSION['login']))
{
echo "Přihlášen jako: ".$_SESSION['login']." <a href=\"".
$_SERVER['PHP_SELF']."?akce=odhlasit\">Odhlasit</a>";
}

?>

Co ve skriptu chybí?
Otevření databáze - počítám s tím, že je otevřená
Ošetření chyb databáze - to se mi nechtělo
Automatické odhlášení - řeším to časovým kódem v databázi, který pokaždém spuštění skriptu přepíšu
Šifrování hesla v databázi - to se mi taky nechtělo, ale funkce md5() si s tím poradí
Chyby - zřejmě nechybí, ale jde mi jen o vysvětlení, jak funguje session

Jak to funguje?
K přenosu dat mezi stránkama, resp. klíče identifikujícího data se používá GET, nebo Cookies, nebo obojí, záleží na nastavení serveru a klienta.

Ještě něco?
Vlastně si to píšu sám pro sebe, abych věděl, až to zapomenu, kam se mám podívat. Nicméně přivítám jakékoliv připomínky.

5 komentářů:

martiner řekl(a)...

... WHERE login = ".$_SESSION['login']."' ...
SQL injection. Not good!

pow řekl(a)...

Ty seš nějakej pověrčivej. Ale díky.
Mimochodem, mě by docela zajímalo, jestli je tam korektně použitej ten SELECT. Respektive, jestli není možný se jenom zeptat aniž bych při tom doloval data z databáze - něco jako SELECT vůbec_nic FROM ... A potom jestli je pro databázi jednoduší vybrat celej řádek, nebo jenom jednu položku.

Štěpán řekl(a)...

SELECT 1 FROM xyz WHERE ...

martiner řekl(a)...

Jo, pověrčivej. To je to správný slovo. Tady se o tom píše víc.

Co se týká rychlosti vybírání: vybrat jenom ty věci, který potřebuješ je vždycky rychlejší než "select *" (minimálně se přenáší míň dat) a vůbec nejrychlejší je vybrat jenom konstantu, jak psal Štěpán. Ten rozdíl může být vidět třeba u databází, který si LOBy ukládají jinam než normální data tabulky.

pow řekl(a)...

štěpán: Jak si to teď napsal, kak jsem si vzpoměl, že už jsem to kdysi viděl na přednášce z databází. Díky

Co se tyce SQL Injection. Já vycházím z toho, že všichni na Internetu jsou hodní (stejně jako já) a tyhle věci nedělají. A když už dělají, tak jenom na serverech Microsoftu.