Session řeší problém bezstavovosti protokolu HTTP, udržíme pomocí ní informace o stavu aplikace a práci uživatele sní. Mechanismus session od prvních přídavných doplňků pro PHP3 doznal řadu změn a od PHP verze 4.1+ je práce se sessions standardně dobře funkční a použitelná. V článku proto jen shrneme určité pojmy a problémy, které nemusejí být při nahlédnutí do manuálu hned jasné.

  • místo pojmu session se také někdy používá český termín "relace", v článku používám oba – pokud hovořím o nějaké jedné konkrétní session a nikoli o metodě, volím český termín.

  • v session můžeme mít také spoustu proměnných (parametrů), které bychom jinak museli předávat (a tedy i přenášet) v URL, což je nejen pracné, ale v případě některých parametrů také ne zrovna bezpečné.

  • pokud máme proměnné v relaci, tyto se vůbec nepřenášejí mezi serverem a počítačem klienta, skript na serveru je dostává přímo z interpretu PHP.

  • doporučeno je využití superglobální proměnné $_SESSION.

Důležité funkce a proměnné používané pro práci se sessions:

funkce význam
session_start() Inicializuje (nastartuje) relaci.
session_destroy() Odstraní všechna data relace (např. při odhlašování uživatele).
$_SESSION[‚promenna‘] Zápis superglobální proměnné pro přístup k proměnné promenna v relaci, dřívější funkcesession_register je nedoporučená.
unset($_SESSION[‚promenna‘]) Zrušení hodnoty proměnné promenna v session, dřívější funkce session_unregister je nedoporučená.
SID Konstanta – v případě, že je relace zahájena a nepracují cookies, obsahuje identifikátor relace pro předání  do URL; pokud pracují cookies, konstanta neexistuje, jméno této konstanty může být změněno nastavením v php.ini.

Nastavení funkce session v php.ini:

session.auto_start Určuje, zda relace budou zahajovány automaticky (obvyklá hodnota je "off"); relaci startujeme dle potřeby funkcí session_start.
session.cache_expire Doba vypršení platnosti session, pokud se s aplikací nepracuje.
session.cookie_lifetime Doba životnosti session (obvykle je 0); cookie identifikátoru session tedy zanikne v okamžiku zavření prohlížeče.
session.cookie_domain Omezení identifikátoru pouze na určitou doménu, obvykle není nastaveno.
session.cookie_path Omezení na určité adresáře v doméně, obvykle je "/", cookie tedy platí pro celou doménu a všechny podadresáře.
session.name Nastavuje jméno identifikátoru relace, obvykle je "PHPSESSID".
session.referer_check Kontrolovat referer při práci s aplikací (bezpečnější proti session stealing), obvykle se nepoužívá.
session.save_handler Kam ukládat hodnoty jednotlivých relací; obvykle do souborů "files".
session.save_path Cesta kam ukládat na serveru soubory relací, častá chyba je nesprávné nastavení a tím nemožnost používat relace.
session.use_cookies Určuje, zda se mají používat cookies pro předávání identifikátoru relace (obvykle nastaveno na "on").
session.use_trans_sid Určuje, že v případě potřeby bude automaticky doplněn identifikátor relace do URL odkazů, do skrytých polí formulářů (obvykle je "on").
arg_separator.output Nastavení v php.ini; určuje znak, kterým jsou oddělovány parametry v URL, tedy i idenfikátor relace, vzhledem k XHTML je dobré výchozí nastavení "&" změnit na "&".

Různých nastavení a proměnných je více, obykle však vystačíme s těmito uvedenými.

Výchozí nastavení PHP (které doporučuji) umožňuje ukládání dat jednotlivých relací do souborů ve zvláštním adresáři na serveru, přičemž je povoleno automatické použití cookies a automatické doplňování identifikátoru session do odkazů a formulářů.

Nyní je dobré si uvědomit následující fakta:

Prvním krokem pro použití session je inicializace pomocí funkce session_start. Častou potíží při prvním použití této funkce na testovacím serveru je chybové hlášení o nedostupnosti jakéhosi adresáře. Tento problém se napraví v konfiguračním souboru PHP, kde je uvedena cesta "session.save_path" neexistující nebo nemá interpret PHP dostatečná práva do uvedeného adresáře zapisovat. Vhodnou úpravou nastavení tak případný problém odstraníme.

Pokud při provádění funkce session_start není identifikátor relace k dispozici, interpret PHP zahájí novou relaci: vytvoří nový identifikátor relace. Kdykoli v průběhu práce s aplikací (tj. na libovolné stránce, v libovolné skriptu, který uživatel aplikace spustí) můžeme do relace proměnné přidávat, odebírat nebo měnit jejich hodnoty, případně je možné celou relaci zrušit (tj. zneplatnit, např. při odhlášení uživatele). Připomínám, že z bezpečnostních důvodů raději používáme superglobální proměnné, i když použití staršího způsobu pomocí funkcí session_register, session_unregister není vyloučeno.

Abychom se vyhnuli možnosti zcizení session přímo na serveru, je dobré nastavit adresář pro ukládání souborů session tak, aby se k němu nemohl nikdo dostat ani přes ftp ani ze spuštěného skriptu

Je-li povoleno použití cookies, aplikace sama automaticky rozhodne, je-li třeba přidávat identifikátor do URL a do formulářů. Pokud cookies pracují, identifikátory se nepřidávají a aplikace tak pracuje rychleji. Automatické doplňování identifikátoru session funguje velmi spolehlivě na relativní odkazy, na formuláře. Ne už však na různé odkazy nebo přesměrování vytvořené javaskriptem nebo jiným jazykem na straně klienta. Na toto je potřeba pamatovat při psaní skriptu a identifikátor pomocí konstant SID doplnit ručně.

<img src="help.gif" alt="nápověda" onclick="window.open(‚help.php?<?php echo SID ?>‘)" />

Je velmi dobré ukládat si ihned při zahájení nové session její identifikátor do databáze. S aplikací se pak mnohem bezpečněji pracuje (zejména tam, kde se session využívá pro předávání autentizace uživatele), lépe se ověří platnost session nebo případné podvržení (kontrola IP adresy a další mechanismy). Vyloženě nutné to však není, session lze použít i samostatně bez databáze a dokonce do ní můžeme vložit IP adresu – např. pro zvýšení komfortu uživatele aplikace (uživatelské nastavení, různí průvodci registrací apod.). Pro bezpečnost můžeme vložit i IP adresu a při práci s aplikací ji kontrolovat i bez použití databáze. I v tomto jednoduchém případe je však třeba vždy po zahájení session (po funkci session_start) ověřit její platnost. To zajístíme tak, že si do session vložíme nějakou pomocnou proměnnou (je možné využít proměnné, kterou již v aplikaci využíváme a která je v session po celou dobu práce s aplikací).

Pokud po zahájení relace proměnná neexistuje, session je neplatná – jde buď o čerstvé zahájení relace a proměnná ještě nebyla inicializována nebo pracujeme se session, která je již neplatná a proměnná tedy není k dispozici. Jakmile to zjistíme, přesměrujeme uživatele na stránku, která zajistí korektní nastavení session. Může to být stránka s dialogem pro přihlášení, ale třeba jen stránka odkazem, kde si uživatel něco zvolí a tím také zahájí novou relaci (například nezadá jméno a heslo ale jen klikne na odkaz, že chce pracovat s aplikací jako host). Tímto postupem se vyhneme tomu, aby bylo možné pracovat s aplikací i když již dávno není platná session daná jejím identifikátorem.

session_start();
if ($_SESSION[‚isvalid‘]!=1)
{ // pokud testovací proměnná neexistuje nebo nemá správnou hodnotu, vynutit např. nové přihlášení
  Header(‚Location: http://server.com/login.php‘);
  Exit;
}

Pomocí nastavení v php.ini lze určit, aby se relace startovaly automaticky; funkci session_start v tom případě nepoužíváme. Relace se tehdy zahajují při spuštění každého skriptu, což může být při běžném použití serveru zbytečný luxus, který ubírá výkon. Tato možnost se však hodí tehdy, pokud máme server vyhrazený pro aplikaci, která využívá relace.

Dobré je si také uvědomit, že při práci s databázovou aplikací můžeme například často používané údaje z databáze vyjmout jen při zahájení relace, vložit je do session a při další práci s aplikací již do databáze nesahat. Hodí se to pro různá uživatelská nastavení nebo konfigurační údaje aplikace, které potřebujeme ve většině skriptů a ušetříme si tak zpomalení aplikace při výběru do databáze. Jen podotýkám, že pokud u takové aplikace změníme některé konfigurační údaje v databázi, v aplikaci se projeví až při novém zahájení session, kdy se do relace načtou aktualizované údaje z databáze.

Důležitá rada na závěr – vyhněte se složitým smyčkám a přesměrováním při zahajování relací a mějte na paměti, že ne všichni mají cookies zapnuté. Zde nejde ani tak o bezpečnost, ale o fakt, kdy by se mohl někdo pokusit nevhodně napsanou aplikaci (nebo přímo server) nabourat tím, že vytvoří robota, který bude hromadně zahajovat stále nové a nové relace, čímž zahltí server. Možnou ochranou je v tomto případě použití databáze a kontrola IP adresy.

Pokud pochopíme zde uvedená pravidla, je použití sessions v PHP velmi snadné a bezpečné.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět