Vše o session

Session je důmyslný nástroj, který nám velmi usnadňuje uchovávání stavových dat a autentizaci uživatele.

Začněmě trochu zeširoka (klidně přeskočte až k dalšímu nadpisu):

Jak mnoho z vás jistě ví, je internet postaven na vzájemné komunikaci počítačů. Tato komunikace se odehrává díky TCP/IP sadě internetových protokolů. Protokoly jsou v této sadě rozděleny do 4 vrstev:

  • vrstva síťového rozhraní (Ethernet,PPP)
  • síťová vrstva (IP,ICMP)
  • transportní vrstva (TCP, UDP)
  • aplikační vrstva (HTTP, FTP, SSL,atd.)

Některé z těchto protokolů jsou stavové (komunikace probíhá pomocí relací, tedy navázání spojení a jeho udržování během komunikace) např.: PPP, TCP, FTP; a nestavové (klient pošle požadavek, server odpoví, konec, žádné udržování relace) např.: Ethernet, IP, HTTP. Toto rozdělení je hodně zjednodušené ale nám bude stačit. Když otevíráme webovou stránku, vyšle prohlížeč pomocí HTTP požadavek na určitý server. HTTP vytvoří dotaz GET a předá ho TCP protokolu. Ten naváže se vzdáleným serverem relaci a bezpečne mu dotaz odešle. Při komunikaci využívá IP protokol. Ten všechny data "balí" do paketů, označí pakety směrovací a zpáteční adresou a předá je protokolu Ethernet nebo třeba PPP. Tyto se postarají o vypravení dat na nebezpečnou cestu internetem.

HTTP

Jak už jsem naznačil výše, je protokol HTTP bezstavový. To v praxi znamená, že okamžitě jakmile HTTP server vyřídí požadavek, zapomene s kým komunikoval a smaže všechny stavové proměnné (zapomene například jaký styl stránky jste zvolil). Stejně tak pracuje i PHP. Po zpracování celého skriptu se všechny proměnné nenávratně smažou. Jsou ale dva případy, kdy potřebujeme uchovávat data mezi požadavky.

  1. Autentizace uživatele
  2. Stavové proměnné

Autentizace uživatele

V mnoha případech potřebujeme vědět s kterým uživatelem, právě teď komunikujeme. Pokud si totiž prohlížejí nějakou webovou stránku dva uživatelé zároveň a jeden je například přihlášen, nepozná server při dalším požadavku, o kterého uživatele se jedná. To je potřeba nějak ošetřit.

Způsoby řešení:

Základní HTTP autentizace - při vstupu na stránku se otevře malé okénko, kam uživatel vyplní jméno a heslo.

Výhody: dá se nastavit přímo v konfiguraci HTTP serveru a proto se pomocí ní dají chránit všechny druhy souborů (i gif apod.).

Nevýhody: neumožňuje ukládat další informace o uživateli. Okénko se nedá stylovat. Funguje jen u Apache 2 a vyšší.

Cookie - po přihlášení ve vašem formuláři se odešle cookie s jednoznačným identifikačním klíčem (náhodně generovaný řetězec). Při dalším požadavku odešle prohlížeč s dotazem také cookie a tak bude server vědět s kým má tu čest.(Musí si ale uložit do DB nebo na disk informace o klíči)

Výhody: jednoduchý, relativně bezpečný, nezatěžuje disk serveru ani výpočetní výkon, spolu s klíčem se dají odeslat i stavové proměnné (název uživatele, nastavení atd.)

Nevýhody: cookie se dá zakázat, pokud přenášíme velký objem stavových proměnných, zatěžujeme linku.

Mungování řetězce dotazu - na konec každého odkazu se doplní identifikační klíč( index.php?id=jhdfk454fsfd5ffsd54fsd54f8f48f) a uloží se do DB nebo na disk. Díky tomu opět server kdykoliv ví, s kým jedná.

Výhody: funguje vždy

Nevýhody: vypadá nehezky, vadí vyhledávačům, pokud někomu pošleme odkaz s tímto klíčem a je klíč ještě platný, tak tento systém narušíme.

Session - spojuje výhody předešlých řešení.

Výhody: Používá cookie k uchovávání identifikačního klíče. Když je cookie zakázáno, použije mungování. Ukládá data (kromě klíče) na server.

Nevýhody: říká se o něm, že je pomalé a zatěžuje výkon (více dále)

Jak funguje session

Session se spousti prikazem session_start(); Následně zjistí, jestli mezi cookies není nějáká s názvem PHPSESSID (může se lišit, záleží na nastavení v php.ini) a jestli není tato proměnná v superglobálním GET. Když nic neobjeví, odešle cookie s 32 bajtovým identifikačním klíčem (případně munguje řetězec) a založí na disku ve složce php/tmp (opět se může lišit) soubor sess_identifikační klíč (bez koncovky). Pokud něco v cookie nebo URL identifikační klíč objeví, tak se pokusí na disku najít soubor, který tento klíč obsahuje v názvu.

Pokud něco zapíšeme do superglobálního pole $_SESSION, uloží se tato data do již zmíněného souboru na disku. V cookie, které putuje k uživateli, je pouze identifikační klíč, který zabezpečí, aby měl uživatel k dispozici svoje data. Data se zapisují do úložiště (souboru) podobně jako výstup funkce serialize. Pouze s několika málo rozdíly: Zápis v session úložišti:

user|s:6:"dundee";password|s:32:"5280e84f8be43fcbc874a94aa5899d2a";

Serializované superglobální pole $_SESSION:

a:2:{s:4:"user";s:6:"dundee";s:8:"password";s:32:"5280e84f8be43fcbc874a94aa5899d2a";}

Jak je vidět, je zápis docela podobný (když si odmyslíme zápis pole u druhého příkladu). Rozdílem je, že název proměnné se u session odděluje od hodnoty svislou čarou a že název není v uvozovkách. U složitějších typů proměnných (objektů) bude rozdílů samozřejmě více.

Koloběh session:

  1. inicializace, načtení cookie a GET, vytvoření pole $_SESSION z úložiště
  2. skipt pracuje svévolně s polem $_SESSION
  3. na konci zpracování skrpitu se ukládá $_SESSION zpět do úložiště
  4. odesílá se cookie s identifikačním klíčem
  5. ukončení, vyčištění $_SESSION
  6. garbage collector – odstraní prošlé soubory z úložiště

Jak je to s výkonem: Podle mých osobních měření je tvrzení, že je session pomalejší, než přímé odesílání cookie, a že více zatěžuje server, bohužel pravdivé. Průměrný čas běhu skriptu se session: 0.0020759676086957 Průměrný čas běhu skriput s cookie: 0.0014722815686275 Rozdíl ve prospěch cookie: 0.0006036860400682

Jak vidíte, rozdíl není až tak zásadní (ve prospěch session mluví také fakt, že pro testování cookie jsem nenapsal obdobu garbage collectoru). Je tedy jasné, že pokud potřebujete uložit pouze výběr jazykové mutace, výběr tématu grafiky apod. je vhodnější zvolit cookie. Pokud ovšem potřebujeme uložit větší objem dat, je jednodušší zvolit session.

Hodnocení

Komentáře

2006-10-10 14:06:21

Nemohl bys napsat nějaký příklad??? Nebo mi třeba poslat, chtěl bych si udělat na stránkách přihlašování - s tím session. Nemáš nějaký kontakt? kdyžtak napiš na můj mail DreadDeath@seznam.cz

[2] Martin
2007-08-06 09:13:34

Přesně používám ten typ těch složitějších session. Takže při přístupu k nim musím třeba zapisovat $_SESSION[kriterium][$i][nazev], což mi sice u mě doma na Apachy funguje, ale nefunguje mi to na serveru Pipni. Nevis, cim by to mohlo byt? (je teda pravda, ze oni pouzivaji PHP 5.2.3 a ja 4.4.4 - ale nikde jsem nenasel, ze by to melo delat problemy)

Na tento komentář odpověděl [3] Dundee
[3] Dundee
2007-08-08 23:14:14

#2 Martin: S problematikou uchovávání vícerozměrných polí v session jsem se setkal několikrát. Bohužel se mi nepodařilo přijít na to, jak problém vyřešit. Nakonec jsem vždy musel změnit strukturu dat, aby v session zůstali uchovány.

Komentáře již nelze přidávat