Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
PHP
Session v PHP
php
19. března 2003, 00.00 | Co to vlastně session jsou? Co nám nabízejí a jak nám usnadňují práci? Proč a jak je používat?
Článek se snaží na tyto otázky odpovědět.
Co od session můžeme očekávat a co potřebujeme?
1) identifikaci uživatele - abysme mohli nějaké proměnné uchovávat, musíme vědět od koho pocházejí
2) uchovávání obsahu proměnných
Abychom jednotlivé uživatele od sebe rozeznali, potřebujeme nějaký identifikátor prohlížeče (standardně býva v PHP pojmenován PHPSESSID, často se používá i authid). Jeho název můžeme nastavit v php.ini nebo pomocí funkce session_name (o tom více později). Ten musí být předáván s každým požadavkem na server. Skript vygeneruje identifikátor a předá ho uživateli (není vhodné generovat identifikátor hned na úvodní stránce, komplikuje to práci vyhledávačů a často ani neregistrují URL, které předává parametry (metoda GET)). Lepší je generovat ho později, třeba při úspěšném přihlášení uživatele nebo třeba při vložení prvního zboží do nákupního koše. Jsou dvě možnosti předávání:
Cookies - při každém dalším přístupu se v požadavku klienta posílají i cookies (a samozřejmě i ta naše s identifikátorem).
URL parametr - přímo v odkazech (metoda get) a formulářích (post nebo get). Ke každému skriptu volanému odkazem se přidá identifikátor (např. <A href="pokus.php?authid=5465967416161654964664">odkaz</A>) nebo ve formuláři:
<FORM action="pokus.php">
<INPUT type=hidden name="authid" value="5454657469487912314564654">
.
.
.
</FORM>
Oba způsoby mají své výhody a nevýhody. Použití cookie je jednodušší, ale uživatel je může vypnout. Potom přestávají správně fungovat i session. V druhém případě nás uživatel nemůže překvapit, když cookies nepoužívá. Bohužel je to ale trochu náročnější na tvůrce skriptu. Když ve skriptu identifikátor zapomenete, skript by nefungoval správně. Další a hlavní nevýhodou při předávání v URL je možnost zjištění identifikátoru jinou osobou (například pomocí proměnné HTTP_REFERRER, v logu proxy serveru, ...). Pokud by skript spoléhal jen na identifikátor, mohla by jiná osoba se znalostí identifikátoru získat přístup na stránky, z jejichž URL identifikátor získal. Při použití v URL je proto vhodné kombinovat session ještě třeba s kontrolou IP adresy a času.
Možná se ptáte proč session jsou, když stejně musím předávat identifikátor. Mohl bych přece předávat rovnou proměnné. Uvědomte si, že ale stačí předávat jednu proměnnou (v aplikaci bez session by se jich mohlo předávat o dost více). A hlavně: php lze nastavit tak, že se o předávání starat nemusíte a php ho bude předávat automaticky.
Nastavení
Nastavit chování můžeme několika způsoby. Vše lze nastavit v php.ini pomocí následujících direktiv:
session.save_handler - určuje, co se použije pro ukládání dat session (soubor, databáze)
session.save_path - adresář pro ukládání souborů session (použije se v případě session.save_handler = files)
session.name - jméno identifikátoru. Stejně se bude jmenovat i cookie, pokud k předávání identifikátoru cookie použijete
session.auto_start - Pokud nastavíme na 1, budou se session spouštět automaticky, jinak je musíme spouštět ručně funkcí session_start().
session.use_cookies - určuje, že se pro předávání identifikátoru použije cookie
session.use_only_cookies - dovoluje k přenosu identifikátoru použít pouze cookie
session.cookie_lifetime - nastavení doby platnosti cookie ve vteřinách. Je možné nastavit 0, cookie pak platí do ukončení prohlížeče
session.cookie_path - cesta uložená v cookie
session.cookie_domain - doména uložená v cookie
session.cookie_secure - dovoluje poslat cookie jen na zabezpečeném spojení (HTTPS)
session.gc_probability - pravděpodobnost, že se garbage collection spustí při každém požadavku. Udává se v procentech. Není dobré nastavovat vysokou hodnotu. Garbage collector je poměrně náročný na výkon. Je lepší aby se spouštěl méně a mazal více dat, než aby se spouštěl při každém požadavku a nemazal nic.
session.gc_maxlifetime - určuje po kolika vteřinách budou nepoužívaná data považovaná za smetí a vyčištěna
session.referer_check - kotrola HTTP Referer
session.entropy_file - cesta k externímu souboru, který se použije jako externí zdroj ke generování identifikátoru
session.entropy_length - určuje kolik bajtů se přečte z externího souboru
session.cache_limiter - nastavení způsobu kešování
session.cache_expire - nastavení expiračního času pro kešování
session.use_trans_sid - nastavuje automatické předávání identifikátoru
url_rewriter.tags - určuje, které html tady budou upraveny (bude do nich přidán identifikátor, pokud je nastaveno session.use_trans_sid)
Vždy ale přístup k php.ini nemáme (např. hosting). Potom můžeme použít funkci ini_set. Funkce změní hodnotu konfigurační volby a vrátí předchozí hodnotu. Při chybě vrátí FALSE.
Př: ini_set('session.name','authid');
Ini_set nám dovolí nastavit téměř vše z nastavení session. Všechny direktivy patří mají příznak PHP_INI_ALL a je možné je nastavovat z uživatelských skriptů. Jedinou vyjímkou je session.use_trans_sid (PHP_INI_SYSTEM, PHP_INI_PERDIR). Lze měnit v php.ini, httpd.conf nebo .htaccess. Podrobnosti jak a co lze nastavit je nad rámec tohoto článku. Podrobnosti naleznete na www.php.net.
Dalším způsobem jak něco nastavit je možné pomocí funkcí přímo k tomu určených, například: session_set_cookie_params, session_cache_limiter.
Funkce
Pro práci se session se nám budou hodit následující funkce:
session_start - nastaví session data
session_register - registrování proměnné do session
session_is_registered - zjišťuje, jestli je proměnná registrovaná v session
session_id - nastaví nebo vrátí session id
session_name - nastaví nebo vrátí session name
Ještě se nám budou hodit fce isset a empty. Nebudu zde vypisovat jak přesně která funkce pracuje, to si jistě najdete na www.php.net v přehledu funkcí.
SID
Pro usnadnění práce při předávání identifikátoru slouží konstanta SID. Dala by se zapsat jako jmeno_identifikatoru=hodnota ( stejného výsledku dosáhnete zápisem echo session_name()."=".session_id(); ).
Př. 1:
header ('Location: http://'.$_SERVER['SERVER_NAME'].'/index2.php?'.SID);
Př. 2:
<A href=index2.php?<? echo SID ?>>
Bezpečnost
Než přejdeme k ukázce skriptu, ještě je třeba zmínit jednu důležitou věc. Už jste určitě slyšeli o superglobálních polích, globálních proměnných, register_globals, ... Z důvodu vyšší bezpečnosti se ve verzi php 4.1.0 objevilo superglobální pole $_SESSION (stejné jako známe například $_GET, $_POST,...).
Ve starších verzích php, ale pole $_SESSION nemáme a proměnné musíme registrovat pomocí funkcí session_register. Při nastavení register_globals = off ale takový způsob registrace nefunguje.
Je bezpečnější používat pole $_SESSION. V opačném případě (session_register a register_globals =on) nemáme totiž jistotu, odkud data pocházejí. Pokud máme například skript, ve kterém je v session proměnné $prihlaseny určeno, zda uživatel může do systému, můžeme narazit:
session_register ("prihlaseny");
if ( $prihlaseny == 1 ) {
// jsem v systemu
}
Pokud ale skript zavolám index.php?prihlaseny=1 dostanu se také do systému. Protože podmínka je splněna. Když ale budu testovat podle následujícího skriptu, už budeme mít jistotu, že v proměnné je skutečně hodnota ze session.
if ($_SESSION['prihlaseny'] == 1) {
// jsem v systemu
}
[-more-]{Praktická ukázka} Praktická ukázka
Jak registrovat proměnné v php starším 4.1.0 (nemáme pole $_SESSION):
if (!session_is_registered("promenna")) {
session_register("promenna");
$promenna = 12345; // ted uz je mozne pracovat s $promenna jako s kazdou jinou promenou
}
session_unregister("promenna"); // odregistrovani
Jak registrovat proměnné při php 4.1.0 a vyšším:
V tomto případě přistupujeme k proměnným session přes superglobální pole $_SESSION. Není potřeba proměnné registrovat, stačí jen hodnoty deklarovat:
if (!isset($_SESSION["promenna"])) {
$_SESSION["promenna"] = 12345;
}
unset ($_SESSION["promenna"]); // odregistrovani
Ukázali jsme si dva způsoby práce se session. Oba je možné používat, ale:
Pokud chcete psát bezpečné skripty, u kterých nezáleží na nastavení register_globals, používejte pole $_SESSION. (pro toto je nutné mít ale php verze 4.1.0 nebo vyšší). Musíte si ale vybrat jen jeden způsob. Pokud používáte pole $_SESSION, už nepoužívejte funkce session_register, session_unregister a session_is_registered.
Příklad je záměrně rozdělen do dvou skriptů, aby bylo jasně vidět, že k deklaraci dochází v jiném skriptu. Po spuštění skriptu a 5 kliknutích zjistíte, že se na výstupu objeví řetězec, který jsme deklarovali v prvním skriptu. Ukázky jsou dvě: pro verze php starší než 4.1.0 a pro novější. V příklad je použito nastavení session.use_trans_sid = 0, session.use_cookie=1 a session.auto_start = 0.
Praktická ukázka pro php vyšší 4.1.0 a vyšší:
index.php:
|
index2.php:
|
Praktická ukázka pro php do verze 4.1.0:
index.php:
|
index2.php:
|
Konec práce se session
Pokud už hodnoty ze session nejsou potřeba, můžeme se jich jednoduše zbavit. To provedeme ve dvou krocích - vyprázdnění všech proměnných v session a zrušení vlastní session:
|
Pár rad na závěr
Ještě bych rád upozornil, že hodnoty v session se neudrží donekonečna. Je vhodné kód skriptu ošetřit na tuto možnost.
Pokud na přenos identifikátoru používáme cookie (session.use_cookies = 1 v php.ini), je nutné volat session_start na začátku skriptu ještě před jakýmkoli výstupem. Funkce session_start totiž přidává k hlavičkám cookie a jak jistě víte, hlavičky se posílají jako první.
Spoluautor: Ondrej Ivanič(, )
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007