Vypršení životnosti relace (session) - problém a řešení

  • 9.6.2009
  • Tomáš Hojgr

Relace („sessions“) se ve webových aplikacích používají k uchování stavu aplikace spuštěné na webovém prohlížeči uživatele. Jelikož je HTTP protokol standardně bezstavový, tak je tímto dána možnost uchovat si na serveru určitá data, která nám pomáhají uchovat si požadavky na stránku odeslané uživatelem a při následném zobrazení stránky tyto informace použít.

Kde je problém?

Každá vytvořená relace má však svou určenou životnost. Vždy končí při zavření prohlížeče, avšak také končí při uplynutí doby, na kterou je nastavena. Ztráta relace na stránkách může být někdy nepříjemná.

Může se projevit stejně jako v těchto reálných a zcela běžných případech:

  • ztráta vložených produktů do košíku, jelikož jsme si při nákupu v internetovém obchodu odskočili na oběd (čímž se po určitém čase session zneplatnila)
  • ztráta session v době, kdy píšeme dlouhý článek přímo ve webovém editoru na určitém webu a při uložení nám server odpoví tím, že bychom se měli znovu přihlásit, čímž jsme samozřejmě přišli o celý napsaný článek

Jak tedy zabezpečit webové aplikace, aby se relace neztrácela?

1. Navýšení hodnoty životnosti relace

Jednou z možností je navýšení hodnoty životnosti relace přímo v nastavení PHP.INI (hodnota session.gc_maxlifetime).

Tuto operaci však nedoporučuji a to z tohoto důvodu:

„Relace jako taková je vlastně soubor proměnných, případně i objektů, které jsou PHP strojem serializovány (rozuměj převedeny do stavu, kdy lze hodnoty bez obtíží uložit na disk) a uloženy do souboru adresáře relací na serveru. Jelikož je pro každého návštěvníka stránky vytvořená nová relace, tak při návštěvnosti např. 4000 lidí denně je nutno vytvořit 4000 souboru v adresáři (pokud teda nastavíme životnost na 24 hodin). A pokud navíc na serveru provozujeme více webových aplikací a všechny tyto aplikace ukládají své relace do jediného adresáře (standardní situace), tak máme hned v adresáři několik tisícovek souborů. I selský rozum nám napovídá, že následné hledání jediného souboru v této změti souborů při načtení každé další webové stránky, nám server znatelně zpomalí ne-li přímo celý server shodí. „

Druhou, a mnohem lepší možností, je vytvořit si službu, která nám bude životnost relace neustále prodlužovat.

2. Prodlužování relace

Pokud si představíme, jakým způsobem PHP pracuje s relací, tak je velmi jednoduché vytvořit si skript, který nám bude automaticky, po nějakém daném čase, životnost relace prodlužovat.

Jak už jsem psal výše, relace v PHP je serializovaný soubor, který obsahuje soubor proměnných nebo objektů, a je uložen v adresáři pro relace. Název tohoto souboru je shodný s hodnotou cookie SESID, která je zasílána v požadavku od uživatele. V PHP kódu po zavolání funkce session_start() (nebo pokud je zapnutá v PHP.INI direktiva session.auto_start) se v adresáři pro relace začne hledat soubor s tímto názvem. Pokud je nalezený a je platný (jeho životnost ještě nevypršela), tak si jej „odserializuje“ (převede zpět do podoby proměnné či objektu) a uloží si veškerý obsah do globální proměnné SESSION. Při skončení skriptu PHP automaticky zavolá funkci session_write_close, která serializuje všechny hodnoty v proměnné SESSION a uloží je do adresáře pro relace pod názvem SESID.

Důležité je zde zmínit, že životnost se v nových verzích PHP (od verze 4.2.3) zjišťuje pomocí funkce MTIME, která vrací čas modifikace souboru (ve starších verzích se používala funkce ATIME, tedy čas, kdy byl soubor naposledy otevřen, která způsobovala problémy na systému WINDOWS, který tuto funkci nepodporoval) .

Pokud tedy víme, jak relace pracují, je možné vytvořit dva jednoduché soubory, které nám budou po určitém intervalu volat funkci session_start na serveru a tím neustále prodlužovat životnost relace.