Seje
HTTP je protokol brez stanja, vendar mora skoraj vsaka aplikacija ohranjati stanje med zahtevami, npr. vsebino nakupovalne košarice. Za to se uporablja seja. Oglejmo si
- kako uporabljati seje
- kako se izogniti navzkrižju imen
- kako nastaviti potek veljavnosti
Pri uporabi sej vsak uporabnik prejme edinstven identifikator, imenovan ID seje, ki se posreduje v piškotku. Ta služi kot ključ do podatkov seje. Za razliko od piškotkov, ki so shranjeni na strani brskalnika, so podatki o seji shranjeni na strani strežnika.
Sejo konfiguriramo v konfiguraciji, pri čemer je pomembna izbira časa izteka veljavnosti.
Sejo upravlja objekt Nette\Http\Session, ki ga dobimo
s posredovanjem z uporabo vbrizgavanja odvisnosti. V predstavitvah
preprosto pokličemo $session = $this->getSession()
.
Začetek seje
Privzeto bo Nette samodejno zagnal sejo v trenutku, ko bomo začeli brati iz nje ali vanjo pisati podatke. Če želite sejo
zagnati ročno, uporabite $session->start()
.
PHP ob začetku seje pošlje glave HTTP, ki vplivajo na predpomnjenje, glejte session_cache_limiter, in po možnosti piškotek z ID seje. Zato je treba sejo vedno začeti, preden brskalniku pošljemo kakršen koli izpis, sicer se vrže izjema. Če torej veste, da bo seja uporabljena med prikazovanjem strani, jo pred tem ročno zaženite, na primer v predstavitvenem programu.
V načinu za razvijalce Tracy zažene sejo, ker jo uporablja za prikaz preusmeritev in vrstic z zahtevami AJAX v vrstici Tracy.
Razdelek
V čistem jeziku PHP je shramba podatkov seje izvedena kot polje, ki je dostopno prek globalne spremenljivke
$_SESSION
. Težava je v tem, da so aplikacije običajno sestavljene iz več neodvisnih delov, in če imajo vsi na
voljo le eno isto polje, bo prej ali slej prišlo do kolizije imen.
Nette Framework rešuje težavo tako, da celoten prostor razdeli na dele (predmete Nette\Http\SessionSection). Vsaka enota nato uporablja svoj odsek z edinstvenim imenom in do trkov ne more priti.
Odsek dobimo od upravitelja sej:
$section = $session->getSection('unique name');
V predstavitvenem programu je dovolj, da pokličemo getSession()
s parametrom:
// $this je Predavatelj
$section = $this->getSession('unique name');
Obstoj odseka lahko preverimo z metodo $session->hasSection('unique name')
.
S samim odsekom je zelo enostavno delati z metodami set()
, get()
in remove()
:
// pisanje spremenljivk
$section->set('userName', 'franta');
// branje spremenljivke, vrne nič, če ne obstaja
echo $section->get('userName');
// odstranjevanje spremenljivke
$section->remove('userName');
Za pridobitev vseh spremenljivk iz razdelka je mogoče uporabiti cikel foreach
:
foreach ($section as $key => $val) {
echo "$key = $val";
}
Kako nastaviti potek veljavnosti
Iztek veljavnosti lahko nastavite za posamezne odseke ali celo posamezne spremenljivke. Uporabnikova prijava lahko poteče čez 20 minut, vendar si lahko še vedno zapomnimo vsebino nakupovalne košarice.
// razdelek poteče po 20 minutah.
$section->setExpiration('20 minutes');
Tretji parameter metode set()
se uporablja za nastavitev izteka veljavnosti posameznih spremenljivk:
// spremenljivka 'flash' poteče po 30 sekundah
$section->set('flash', $message, '30 seconds');
Ne pozabite, da mora biti čas poteka celotne seje (glejte konfiguracijo seje) enak ali višji od časa, nastavljenega za posamezne odseke ali spremenljivke.
Preklic predhodno nastavljenega izteka je mogoče doseči z metodo removeExpiration()
. Takojšen izbris celotnega
odseka bo zagotovljen z metodo remove()
.
Dogodki $onStart, $onBeforeWrite
Objekt Nette\Http\Session
ima dogodka
$onStart
in $onBeforeWrite
, zato lahko dodate povratne klice, ki se kličejo po začetku seje ali preden
se seja zapiše na disk in nato zaključi.
$session->onBeforeWrite[] = function () {
// zapisovanje podatkov v sejo
$this->section->set('basket', $this->basket);
};
Upravljanje seje
Pregled metod razreda Nette\Http\Session
za upravljanje sej:
start(): void
Začne sejo.
isStarted(): bool
Ali se je seja začela?
close(): void
Konča sejo. Seja se samodejno konča ob koncu scenarija.
destroy(): void
Konča in izbriše sejo.
exists(): bool
Ali zahteva HTTP vsebuje piškotek z ID seje?
regenerateId(): void
Ustvari nov naključni ID seje. Podatki ostanejo nespremenjeni.
getId(): string
Vrne ID seje.
Konfiguracija
Seanso konfiguriramo v konfiguraciji. Če pišete aplikacijo, ki ne uporablja vsebnika DI, jo konfigurirajte s temi metodami. Poklicati jih je treba pred začetkom seje.
setName(string $name): static
Nastavi ime piškotka, ki se uporablja za prenos ID seje. Privzeto ime je PHPSESSID
. To je uporabno, če na istem
spletnem mestu uporabljate več različnih aplikacij.
getName(): string
Vrne ime sejnega piškotka.
setOptions(array $options): static
Konfigurira sejo. Mogoče je nastaviti vse direktive seje
PHP (v obliki camelCase, npr. namesto session.save_path
napišite savePath
) in tudi readAndClose.
setExpiration(?string $time): static
Nastavi čas neaktivnosti, po katerem se seja izteče.
setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static
Nastavi parametre za piškotke. Privzete vrednosti parametrov lahko spremenite v konfiguraciji.
setSavePath(string $path): static
Nastavi imenik, v katerem so shranjene datoteke sej.
setHandler(\SessionHandlerInterface $handler): static
Nastavi obdelava po meri, glejte dokumentacijo PHP.
Najprej varnost
Strežnik domneva, da komunicira z istim uporabnikom, dokler zahteve vsebujejo isti ID seje. Naloga varnostnih mehanizmov je zagotoviti, da to vedenje res deluje in da ni možnosti zamenjave ali kraje identifikatorja.
Zato ogrodje Nette Framework ustrezno konfigurira direktive PHP za prenos identifikatorja seje samo v piškotkih, preprečevanje dostopa iz JavaScripta in ignoriranje identifikatorjev v naslovu URL. Poleg tega v kritičnih trenutkih, kot je prijava uporabnika, ustvari nov identifikator seje.
Funkcija ini_set se uporablja za konfiguracijo PHP, vendar je njena uporaba pri nekaterih storitvah spletnega gostovanja žal prepovedana. Če je to vaš primer, poskusite prositi ponudnika gostovanja, da vam to funkcijo dovoli ali vsaj ustrezno konfigurira svoj strežnik.