Kako postaviti pametne telefone i računala. Informativni portal
  • Dom
  • OS
  • Zamke korištenja sesija u PHP-u. Korištenje sesija - rad s PHP sesijama

Zamke korištenja sesija u PHP-u. Korištenje sesija - rad s PHP sesijama

Web poslužitelj ne održava trajnu vezu s klijentom, a svaki zahtjev se tretira kao novi, bez ikakve veze s prethodnim.
Odnosno, ne možete niti pratiti zahtjeve istog posjetitelja, niti spremati varijable za njega između pregleda zasebnih stranica. Sesije su izmišljene da riješe ova dva problema.
Zapravo, sesije su, ukratko, mehanizam koji vam omogućuje jedinstvenu identifikaciju preglednika i kreira datoteku za ovaj preglednik na poslužitelju, koji pohranjuje varijable sesije.

Neću detaljno opisivati ​​potrebu za takvim mehanizmom. Riječ je o takvim udžbeničkim slučajevima kao što su košarica u e-trgovini, autorizacija, kao i ne sasvim trivijalni problemi, kao što je, na primjer, zaštita interaktivnih dijelova stranice od neželjene pošte.

U principu, prilično je lako napraviti svoj vlastiti analog sesija, ne funkcionalan kao ugrađeni PHP, ali sličan u biti. O kolačićima i bazi podataka.
Kada tražimo skriptu, gledamo je li stigao kolačić s određenim imenom. Ako nema kolačića, postavite ga i upišite novi redak s korisničkim podacima u bazu podataka. Ako postoji kolačić, čitamo iz baze podataka. Uz još jedan zahtjev brišemo stare zapise iz baze i sada imamo spreman mehanizam sesije. Uopće nije teško. Ali postoje neke nijanse zbog kojih je poželjno koristiti ugrađeni mehanizam sesije.

Ako je omogućen samo prvi, tada na početku sesije (na svakom pozivu session_start ()) za klijenta je instaliran kolačić. Preglednik ispravno vraća ovaj kolačić sa svakim sljedećim zahtjevom, a PHP ima identifikator sesije. Problemi počinju ako preglednik ne vrati kolačiće. U tom slučaju, PHP će uvijek započeti novu sesiju bez primanja kolačića s identifikatorom, a mehanizam neće raditi.

Ako je omogućen samo drugi, kolačić nije postavljen. I ono što se događa je, radi čega se, u osnovi, zapravo isplati koristiti ugrađeni mehanizam sesije. Nakon što skripta obavi svoj posao, a stranica je u potpunosti formirana, PHP sve to pregleda i dodaje ID sesije svakoj poveznici i svakom obrascu. Izgleda otprilike ovako:
Indeks preobraziti se u
Indeks
a obrascima se dodaje skriveno polje

A preglednik će, kada kliknete na bilo koju poveznicu, ili kada kliknete na gumb u obrascu, u zahtjevu poslati varijablu koja nam je potrebna - identifikator sesije!
Iz očitih razloga, ID se dodaje samo relativnim vezama.

Teoretski, u našim domaćim sesijama o kolačićima i bazi podataka, možete ručno dodijeliti prijenos id-a svim poveznicama - i tada će naše vlastite sesije raditi neovisno o kolačićima. Ali, vidite – ugodnije je kad netko drugi radi ovaj posao? ;-)

Obje su opcije omogućene prema zadanim postavkama u novijim verzijama PHP-a. Kako PHP to rješava? Cook je uvijek izložen. A veze se automatski dovršavaju samo ako PHP ne pronađe kolačić s ID-om sesije. Kada korisnik prvi put posjeti stranicu tijekom ove sesije, dobiva kolačić, a veze se dodaju. Na sljedeći zahtjev, ako su kolačići podržani, PHP vidi kolačić i prestaje dovršavati veze. Ako kolačići ne rade, PHP nastavlja ispravno dodavati id poveznicama i sesija se ne gubi.
Korisnici koji rade kolačiće vidjet će dugu vezu s ID-om samo jednom.

Fuh. Sa završenim prijenosom identifikatora.
Sada ostaje na njega vezati datoteku s podacima na strani poslužitelja.
PHP će to učiniti umjesto nas. Dovoljno je samo napisati
početak_sesije ();
$ _SESSION ["test"] = "Zdravo svijete!" ;

A PHP će zapisati test varijablu u datoteku povezanu s ovom sesijom.
Ovdje postoji vrlo važna točka.
Niz $ _SESSION- poseban.
U njemu se, naime, nalaze varijable koje želimo učiniti dostupnima u raznim skriptama.
Da biste postavili varijablu u sesiju, jednostavno je dodijelite elementu polja $_SESSION.
Da biste dobili njegovu vrijednost, dovoljno je pozvati se na isti element. Primjer će biti u nastavku.

Sakupljanje smeća - PHP je također uključen u uklanjanje zastarjelih datoteka. Kao i kodiranje podataka i hrpa drugih potrebnih stvari. Kao rezultat ove njege, rad sa seansama je vrlo jednostavan.
Tu smo, naime, došli do primjera rada sjednica.
Primjer je vrlo mali:
početak_sesije ();

jeka "Ažurirali ste ovu stranicu"... $ _SESSION ["counter"] ++. "jednom.";
jeka "
ažuriranje ";
?>

Provjeravamo imamo li varijablu brojača u sesiji, ako ne, onda je kreiramo s vrijednošću 0, a zatim ispišemo njezinu vrijednost i povećamo je za jedan. Povećana vrijednost bit će upisana u sesiju, a sljedeći put kada se skripta pozove, varijabla će imati vrijednost 1 i tako dalje.
Sve je vrlo jednostavno.

Da biste imali pristup varijablama sesije na bilo kojoj stranici web-mjesta, trebate napisati SAMO JEDAN (!) Red na samom početku SVAKE datoteke u kojoj su nam potrebne sesije:
početak_sesije ();
Zatim se pozovite na elemente niza $_SESSION. Na primjer, provjera autorizacije izgledala bi otprilike ovako:
početak_sesije ();
ako ($ _SESSION ["autorizirano"]<> 1 ) {
zaglavlje ("Lokacija: /auth.php");
Izlaz;
}

Uklanjanje varijabli iz sesije.
Ako imate register_globals = isključeno, samo napišite
poništeno ($ _ SESSION ["var"]);
Ako ne, onda blizu Moram pisati s njom
session_unregister ("var");

Najčešće pogreške koje PHP daje kada pokušava raditi sa sesijama su:
Njih dvoje,
Upozorenje: Nije moguće poslati kolačić sesije - zaglavlja su već poslana
Upozorenje: Nije moguće poslati limitator predmemorije sesije - zaglavlja su već poslana

uzrokovano istim razlogom, rješenje je opisano u ovoj činjenici
Treći,
Upozorenje: otvaranje (/ tmp \ sess_SID, O_RDWR) nije uspjelo: nema takve datoteke ili direktorija (2) u full_script_path na broju retka(prije je izgledala kao Upozorenje: Zapisivanje podataka o sesiji (datoteke) nije uspjelo. Provjerite je li trenutna postavka session.save_path ispravna (/ tmp)),
ako je prevedeno s engleskog, detaljno objašnjava problem: put naveden u php.ini do direktorija u koji su zapisane datoteke sesije nije dostupan. Ovu grešku je najlakše popraviti. Samo napišite imenik koji postoji i u koji se može pisati, na primjer,
session.save_path = c: \ windows \ temp
I ne zaboravite ponovno pokrenuti Apache nakon toga.

Kako se ispostavilo, ljudska inteligencija nema granica i stoga moram objasniti:
treća poruka o pogrešci (direktorij se ne može pronaći) će NEDOSTUPNO dovesti do prve dvije, jer se poruka o pogrešci šalje pregledniku i ne možete koristiti zaglavlja nakon nje. Stoga nemojte žuriti tražiti preuranjeni zaključak, već prvo napišite ispravan put!

Sljedeći najčešći problem pri radu sa sesijama je teško naslijeđe register_globals. NEMOJTE davati varijablama skripte ista imena kao indeksima niza $_SESSION!
S register_globals = uključen, vrijednosti će se prepisati jedna drugu i vi ćete se zbuniti.
A ako register_globals = off, pojavit će se još jedna pogreška: "Vaša skripta se vjerojatno oslanja na nuspojavu sesije koja je postojala do PHP 4.2.3." ... Da biste ga se riješili, uvijek morate inicijalizirati varijable prije upotrebe (ili barem provjeriti postojanje) i ne davati globalnim varijablama imena koja odgovaraju indeksima polja $_SESSION.

Ako ne radi, ali se niti ne prikazuju poruke, dodajte dva retka na samom početku skripte koji su odgovorni za prikaz SVIH pogrešaka na ekranu - sasvim je moguće da postoje pogreške, ali vi jednostavno ne vidite ih.
ini_set ("display_errors", 1);
izvješćivanje o grešci (E_ALL);

ili pogledajte pogreške u error_log. Općenito, tema prikazivanja poruka o pogrešci je izvan dosega ovog članka, stoga se samo pobrinite da ih barem vidite. U ovom odjeljku možete pročitati malo više detalja o rješavanju problema.

Ako ste sigurni da nema grešaka, ali navedeni primjer ionako ne radi, onda je moguće da PHP ne omogućuje prijenos id-a putem url-a, a kolačići iz nekog razloga ne rade.
Pogledajte što imate s kolačićima.
Općenito, ako vaše sesije "ne rade", onda prvo pokušajte ručno prenijeti identifikator sesije, odnosno napravite vezu i dodijelite joj identifikator:
početak_sesije ();
if (! isset ($ _ SESSION ["counter"])) $ _SESSION ["counter"] = 0;
jeka "Ažurirali ste ovu stranicu"... $ _SESSION ["counter"] ++. "jednom.

ažuriranje ";
?>

Kada to činite, provjerite da direktiva session.use_only_cookies nije omogućena, što sprječava PHP da prihvati ID sesije ako je prošao kroz URL.

Ako ovaj primjer ne uspije, onda je problem ili u banalnom pogreške u pisanju(polovica "problema" sa sesijama dolazi od pogrešno napisanog naziva varijable) ili u prestaroj verziji PHP-a: podrška za sesije pojavila se u verziji 4.0, a niz $ _SESSION- u 4.1 (Prije korišteno $ HTTP_SESSION_VARS).
Ako radi, onda je problem u kolačićima. Pratite kakav kolačić poslužitelj stavlja u preglednik, vraća li ga preglednik. Pretraživanje je vrlo korisno dok gledate razmjene HTTP zaglavlja između preglednika i poslužitelja.
Objašnjenje načina na koji kolačići rade je izvan dosega ovog ionako prevelikog teksta, ali barem se pobrinite da poslužitelj pošalje kolačić s identifikatorom, a preglednik se vrati. I dok se identifikatori međusobno podudaraju =)
Postavljanje kolačića bi trebalo izgledati ovako
Set-Cookie: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6;
ili kako
Set-Cookie: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6; put = /
(ako tražite skriptu ne iz korijenskog direktorija)
Odgovor poslužitelja trebao bi izgledati ovako
Kolačić: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6
ili
Kolačić: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6; b = b
ako preglednik vraća druge kolačiće osim ID-a sesije.

Ako preglednik ne vraća kolačiće, provjerite rade li kolačići uopće.
Provjerite ima li domena kojoj pristupate normalan naziv (koji ima barem jednu točku i ne sadrži zabranjene znakove, kao što su podvlake) i izbrišite predmemoriju preglednika - ovo su dva glavna razloga zašto kolačići možda neće raditi.

Ako primjer odavde radi, ali vaš vlastiti kod ne, onda očito problem nije u sesijama, već u algoritmu. Potražite gdje ste izgubili varijablu, prenesite primjer odavde korak po korak, otklonite pogreške u svojoj skripti.

Drugi problem može nastati ako koristite preusmjeravanje zaglavlja ili JavaScript navigaciju.
Činjenica je da PHP automatski dodaje identifikator sesije samo na veze obrasca
, ali to ne čini za zaglavlja, javascript, meta oznake.
Stoga morate ručno dodati identifikator, na primjer, ovako:
header ("Lokacija: /script.php?". session_name (). "=". session_id ());

Također, vrlo rijetko, i potpuno je nejasno odakle dolazi problem, problem je u tome što postavka session.save_handler ima drugu vrijednost osim datoteka. Ako to nije slučaj, ispravite to.

Sigurnost
Sigurnost sesije je velika tema. Stoga ću se usredotočiti na nekoliko glavnih točaka.
Najviše udžbenika je ne proslijediti identifikator kroz adresnu traku. Ovo je napisano čak i u php.ini, ali to ograničava funkcionalnost sesija. Ako odlučite slijediti ovaj savjet, onda osim session.use_trans_sid = 0, ne zaboravite session.use_only_cookies = 1
Preporučljivo je vezati sesiju na IP adresu: na ovaj način, ako je identifikator ukraden, zlikovac ga u većini slučajeva ipak neće moći koristiti.
Preporuča se korištenje session.save_path direktive, uz pomoć koje možete postaviti vlastiti direktorij za spremanje datoteka sesije. To je sigurnije nego kada su pohranjeni u zadanom dijeljenom privremenom direktoriju poslužitelja.

Dodatne informacije:

  • Osim kolačića, mehanizam sesije također šalje zaglavlja koja zabranjuju predmemoriju stranica (isti limitator predmemorije). Za html je to ispravno i potrebno. Ali kada pokušate poslati datoteku sa skriptom koja provjerava autorizaciju, Internet Explorer odbija je preuzeti. To je zbog ovog naslova. Poziv
    session_cache_limiter ("privatno");
    mora riješiti problem prije početka sesije.
  • Čudno, ali u nizu $ _SESSION ne možete koristiti numeričke indekse - $ _SESSION [1], $ _SESSION ["10"]- sesije neće raditi.
  • Negdje između 4.2 i 5.0 nije bilo moguće postaviti session.use_trans_sid s ini_set ()... Počevši od 5.0 to je opet moguće.
  • Prije verzije 4.3.3, PHP kolačić je slao kolačić samo ako zahtjev nije sadržavao identifikator na početku sesije. Sada se kolačić šalje na svaki poziv session_start ()

    Primjer autorizacije korištenjem sesija
    Ilustrirajmo sve navedeno malim primjerom:
    napravimo auth.php datoteku:
    if (isset ($ _ POST ["auth_name"]))
    {
    $ sql = "SELECT * FROM users WHERE name =? S";
    $ red = $ db -> getRow ($ sql, $ _POST ["auth_name"]);
    if ($ red && password_verify ($ _POST ["auth_pass"], $ red ["pass"])) (
    $ _SESSION ["user_id"] = $ redak ["id"];
    }
    zaglavlje ("Lokacija: http: //". $ _SERVER ["HTTP_HOST"]. $ _SERVER ["REQUEST_URI"]);
    Izlaz;
    }

    if (isset ($ _ GET ["action"]) AND $ _GET ["action"] == "odjava") (
    početak_sesije ();
    uništiti sesiju ();
    zaglavlje ("Lokacija: http: //". $ _SERVER ["HTTP_HOST"]. "/");
    Izlaz;
    }

    if (! isset ($ _ SESSION ["user_id"])) (
    ?>








    Izlaz;
    }

    Sada je dovoljno upisati red u sve zaštićene skripte
    zahtijevaju "auth.php";
    U ovom primjeru pretpostavlja se da je sesija već započela i da je veza s bazom podataka stvorena korištenjem Class za siguran i praktičan rad s MySQL-om. Također pretpostavlja da je lozinka hashirana pomoću preporučene funkcije password_hash.
    Primjer zaštićene datoteke:

    početak_sesije ();
    uključiti "safemysql.class.php";
    $ db = novi safemysql (["db" => "test"]);
    uključiti "auth.php";
    ?>
    tajna

    Odjavite se

    OPS! Vrlo korisni linkovi:
    http://www.php.net/manual/ru/ref.session.php - najnovije i ažurirane informacije o podršci sesijama u PHP-u u službenoj dokumentaciji, plus brojni komentari korisnika. Čitanje se toplo preporučuje.
    http://phpclub.ru/manrus/f/ref.session.html - VRLO zastarjeli prijevod ovog poglavlja na ruski, iz dokumentacije koju je preveo Alexander Pyramidin.
    http://phpclub.ru/detail/article/sessions
    Članak pretencioznog naslova "Istina o seansama". Ostavlja ambivalentan dojam. Na početku autor VRLO lako govori o sesijskom mehanizmu, ali metode koje predlaže pred kraj članka potpuno su mutne.

    Članak iz udžbenika Dmitrija Borodina s stranice
    http://php.spb.ru/ se strogo NE preporučuje.
    Dečki, ona je užasno zastarjela. Ne samo da u njemu postoje činjenične netočnosti, već se sesije u PHP-u jednostavno ne koriste dugo vremena.
    Veliko hvala Dimi za nju, ovo je bio prvi članak o sesijama na ruskom, sam sam ga proučavao, ali sada je moram poslati na zasluženi odmor.
    Također, nažalost, zastarjeli su i mnogi drugi članci koji se nalaze na internetu i nisu ažurirani godinama.

  • Pozdrav draga zajednica.

    Prije svega, želim vam se zahvaliti na vrlo korisnom resursu. Više puta sam ovdje pronašao mnogo zanimljivih ideja i praktičnih savjeta.

    Svrha ovog članka je istaknuti zamke korištenja sesija u PHP-u. Naravno, postoji PHP dokumentacija i tona primjera, a ovaj članak nije potpuni vodič. Osmišljen je tako da otkrije neke nijanse rada sa sesijama i zaštiti programere od nepotrebnog gubljenja vremena.

    Najčešći slučaj korištenja sesija je, naravno, autorizacija korisnika. Počnimo s najosnovnijom implementacijom kako bismo je mogli dosljedno razvijati kako se pojavljuju novi izazovi.

    (Kako bismo uštedjeli prostor i vrijeme, ograničit ćemo se na primjere samo funkcijama rada sa sesijama, umjesto da ovdje gradimo punopravnu testnu aplikaciju s prekrasnom hijerarhijom klasa, iscrpnim rukovanjem pogreškama i drugim ispravnim stvarima).

    Funkcija startSession () (// Ako je sesija već pokrenuta, zaustavite izvršavanje i vratite TRUE // (parametar session.auto_start u datoteci postavki php.ini mora biti onemogućen - zadana vrijednost) ako (session_id ()) vrati true; inače vraća session_start (); // Napomena: Prije verzije 5.3.0, funkcija session_start () vraćala je TRUE čak i u slučaju pogreške. // Ako koristite verziju nižu od 5.3.0, izvršite dodatnu provjeru session_id ( ) // nakon poziva session_start ()) funkcija destroySession () (if (session_id ()) (// Ako postoji aktivna sesija, izbrišite kolačiće sesije, setcookie (session_name (), session_id (), time () - 60 * 60 * 24); // i uništimo sesiju session_unset ( ); session_destroy ();))

    Bilješka: Pretpostavlja se da čitatelj ima osnovno znanje o PHP sesijama, pa nećemo pokrivati ​​kako funkcioniraju funkcije session_start () i session_destroy (). Zadaci izgleda obrasca za prijavu i autentifikacije korisnika nisu vezani uz temu članka pa ćemo ih također izostaviti. Samo da vas podsjetim da za identifikaciju korisnika u svakom sljedećem zahtjevu, u trenutku uspješne prijave, moramo spremiti korisnički ID u varijablu sesije (s imenom userid, na primjer), koja će biti dostupna u svim narednim zahtjeva tijekom trajanja sesije. Također je potrebno implementirati obradu rezultata naše funkcije startSession (). Ako funkcija vrati FALSE, prikažite obrazac za prijavu u pregledniku. Ako funkcija vrati TRUE, a varijabla sesije koja sadrži identifikator ovlaštenog korisnika (u našem slučaju, userid) postoji, prikažite stranicu ovlaštenog korisnika (za više detalja o rukovanju pogreškama pogledajte dodatak od 2013-06- 07 u odjeljku o varijablama sesije).

    Zasad je sve jasno. Pitanja počinju kada je potrebno implementirati kontrolu neaktivnosti korisnika (prekid sesije), omogućiti simultani rad više korisnika u jednom pregledniku, a također zaštititi sesije od neovlaštenog korištenja. O tome će biti riječi u nastavku.

    Kontroliranje neaktivnosti korisnika pomoću ugrađenih PHP alata

    Prvo pitanje koje se često postavlja među programerima svih vrsta konzola za korisnike je automatski završetak sesije u slučaju neaktivnosti korisnika. Ne može biti lakše to učiniti s ugrađenim mogućnostima PHP-a. (Ova opcija nije jako pouzdana i fleksibilna, ali razmotrimo je radi potpunosti).

    Funkcija startSession () (// Timeout neaktivnosti korisnika (u sekundama) $ sessionLifetime = 300; if (session_id ()) vrati true; // Postavi životni vijek kolačića ini_set ("session.cookie_lifetime", $ sessionLifetime); // Ako postavljeno je vremensko ograničenje neaktivnosti korisnika, postavite životni vijek sesije na poslužitelju // Napomena: Za proizvodni poslužitelj, preporuča se unaprijed postaviti ove parametre u datoteci php.ini if ​​($ sessionLifetime) ini_set ("session.gc_maxlifetime", $ sessionLifetime ); if (session_start ( )) (setcookie (session_name (), session_id (), time () + $ sessionLifetime); vrati true;) else vrati false;)

    Malo objašnjenja. Kao što znate, PHP određuje koju će sesiju započeti imenom kolačića koji je proslijedio preglednik u zaglavlju zahtjeva. Preglednik, zauzvrat, prima ovaj kolačić od poslužitelja, gdje ga funkcija session_start () postavlja. Ako je kolačić istekao u pregledniku, neće se prenijeti u zahtjevu, što znači da PHP neće moći odrediti koju sesiju treba pokrenuti, te će to smatrati stvaranjem nove sesije. Parametar postavki PHP-a session.gc_maxlifetime, koji je postavljen kao vrijeme čekanja neaktivnosti korisnika, postavlja životni vijek PHP sesije i njime upravlja poslužitelj. Kontrola trajanja sesije radi na sljedeći način (ovdje razmatramo primjer pohrane sesije u privremenim datotekama kao najčešću i zadanu verziju u PHP-u).

    U vrijeme kreiranja nove sesije, datoteka pod nazivom sess_ kreira se u direktoriju postavljenom kao direktorij za pohranjivanje sesija u parametru PHP postavki session.save_path. , gdje - identifikator sesije. Nadalje, u svakom zahtjevu, u trenutku pokretanja postojeće sesije, PHP ažurira vrijeme izmjene ove datoteke. Dakle, u svakom sljedećem zahtjevu PHP, po razlici između trenutnog vremena i vremena posljednje izmjene datoteke sesije, može odrediti je li sesija aktivna, ili joj je životni vijek već istekao. (Mehanizam za brisanje starih datoteka sesije detaljnije je razmotren u sljedećem odjeljku).

    Bilješka: Ovdje treba napomenuti da parametar session.gc_maxlifetime utječe na sve sesije unutar jednog poslužitelja (točnije, unutar jednog glavnog PHP procesa). U praksi to znači da ako na poslužitelju radi nekoliko stranica, a svaka od njih ima svoje vrijeme neaktivnosti korisnika, tada će postavljanje ovog parametra na jednu od stranica dovesti do njegove instalacije i za druge stranice. Isto vrijedi i za dijeljeni hosting. Kako bi se izbjegla ova situacija, zasebni direktoriji sesije koriste se za svako mjesto unutar jednog poslužitelja. Postavljanje puta do direktorija sesije vrši se pomoću parametra session.save_path u datoteci postavki php.ini ili pozivom funkcije ini_set (). Nakon toga, sesije svake stranice bit će pohranjene u zasebne direktorije, a parametar session.gc_maxlifetime, postavljen na jednom od web-mjesta, bit će važeći samo za njegovu sesiju. Ovaj slučaj nećemo detaljno razmatrati, pogotovo jer imamo na lageru fleksibilniju opciju za kontrolu neaktivnosti korisnika.

    Kontroliranje neaktivnosti korisnika pomoću varijabli sesije

    Čini se da prethodna opcija, uz svu svoju jednostavnost (samo nekoliko dodatnih redaka koda), daje sve što nam treba. Ali što ako se svaki zahtjev ne može smatrati rezultatom aktivnosti korisnika? Na primjer, stranica ima mjerač vremena koji povremeno šalje AJAX zahtjev za primanje ažuriranja s poslužitelja. Takav zahtjev se ne može smatrati aktivnošću korisnika, što znači da automatsko produljenje životnog vijeka sesije u ovom slučaju nije ispravno. Ali znamo da PHP automatski ažurira vrijeme izmjene datoteke sesije sa svakim pozivom funkcije session_start (), što znači da će svaki zahtjev dovesti do produljenja životnog vijeka sesije, a timeout neaktivnosti korisnika nikada neće nastupiti. Osim toga, posljednja napomena iz prethodnog odjeljka o zamršenosti parametra session.gc_maxlifetime može se činiti previše zbunjujućom i kompliciranom za implementaciju.

    Kako bismo riješili ovaj problem, napustit ćemo korištenje ugrađenih PHP mehanizama i uvesti nekoliko novih varijabli sesije koje će nam omogućiti da sami kontroliramo vrijeme neaktivnosti korisnika.

    Funkcija startSession ($ isUserActivity = true) ($ sessionLifetime = 300; if (session_id ()) vrati true; // Postavite životni vijek kolačića dok se preglednik ne zatvori (sve ćemo kontrolirati na strani poslužitelja) ini_set ("session.cookie_lifetime ", 0) ; if (! session_start ()) vrati false; $ t = vrijeme (); if ($ sessionLifetime) (// Ako je postavljeno vremensko ograničenje neaktivnosti korisnika, // provjerite vrijeme koje je proteklo od posljednje aktivnosti korisnika / / (vrijeme posljednjeg zahtjeva kada je varijabla sesije zadnje aktivnosti ažurirana) if (isset ($ _ SESSION ["lastactivity"]) && $ t - $ _ SESSION ["lastactivity"]> = $ sessionLifetime) (// Ako je vrijeme koje je proteklo od posljednje korisničke aktivnosti / / više vremenskog ograničenja neaktivnosti, tada je sesija istekla i morate prekinuti sesiju destroySession (); vrati false;) else (// Ako vremensko ograničenje još nije nastupilo, // i ako zahtjev je došao kao rezultat aktivnosti korisnika, // ažuriraj varijablu lastactivity s vrijednošću trenutnog vr emeny, // čime se produžuje vrijeme sesije za još jednu sessionLifetime sekundi if ($ isUserActivity) $ _SESSION ["lastactivity"] = $ t; )) vrati true; )

    Hajde da rezimiramo. U svakom zahtjevu provjeravamo je li dosegnut timeout od posljednje aktivnosti korisnika do trenutnog trenutka, te ako je dostignut, uništavamo sesiju i prekidamo izvršavanje funkcije, vraćajući FALSE. Ako vremensko ograničenje nije dosegnuto, a parametar $ isUserActivity s vrijednošću TRUE proslijeđen funkciji, ažuriramo vrijeme posljednje aktivnosti korisnika. Sve što trebamo učiniti je u skripti za pozivanje odrediti je li zahtjev rezultat aktivnosti korisnika, a ako nije, pozvati funkciju startSession s vrijednošću parametra $ isUserActivity jednakom FALSE.

    Ažuriranje od 07.06.2013
    Obrada rezultata funkcije sessionStart ().

    U komentarima smo primijetili da vraćanje FALSE ne daje potpuno razumijevanje uzroka pogreške, a to je apsolutno točno. Ovdje nisam objavio detaljnu obradu grešaka (volumen članka ionako nije mali), budući da se to ne odnosi izravno na temu članka. Ali s obzirom na komentare, razjasnit ću.

    Kao što možete vidjeti, funkcija sessionStart može vratiti FALSE u dva slučaja. Ili se sesija nije mogla pokrenuti zbog nekih internih grešaka poslužitelja (na primjer, netočne postavke sesije u php.ini), ili je sesija istekla. U prvom slučaju moramo preusmjeriti korisnika na stranicu s greškom da postoje problemi na poslužitelju, te oblikom kontaktiranja podrške. U drugom slučaju moramo prenijeti korisnika na obrazac za prijavu i u njemu prikazati odgovarajuću poruku da je sesija istekla. Da bismo to učinili, moramo unijeti kodove grešaka i vratiti odgovarajući kod umjesto FALSE, te ga provjeriti u metodi pozivanja i postupiti u skladu s tim.

    Sada, čak i ako sesija na poslužitelju još uvijek postoji, bit će uništena prvi put kada joj se pristupi, ako je isteklo vremensko ograničenje neaktivnosti korisnika. I to će se dogoditi bez obzira na to koji je vijek trajanja sesije postavljen u globalnim PHP postavkama.

    Bilješka:Što se događa ako je preglednik zatvoren, a kolačić naziva sesije automatski uništen? Zahtjev poslužitelju sljedeći put kada se preglednik otvori neće sadržavati kolačiće sesije, a poslužitelj neće moći otvoriti sesiju i provjeriti vremensko ograničenje neaktivnosti korisnika. Za nas je to jednako stvaranju nove sesije i ni na koji način ne utječe na funkcionalnost ili sigurnost. Ali postavlja se pošteno pitanje - tko će onda uništiti staru sesiju, ako smo je do sada uništili nakon isteka timeouta? Ili će sada zauvijek visjeti u imeniku sesije? Za čišćenje starih sesija, PHP ima mehanizam koji se zove prikupljanje smeća. Počinje u trenutku sljedećeg zahtjeva poslužitelju i čisti sve stare sesije na temelju datuma posljednje izmjene datoteka sesije. Ali mehanizam prikupljanja smeća se ne pokreće na svaki zahtjev poslužitelju. Učestalost (točnije, vjerojatnost) pokretanja određena je s dva parametra postavki session.gc_probability i session.gc_divisor. Rezultat dijeljenja prvog parametra s drugim je vjerojatnost pokretanja mehanizma prikupljanja smeća. Dakle, da bi se mehanizam čišćenja sesije pokrenuo na svaki zahtjev poslužitelju, ti parametri moraju biti postavljeni na jednake vrijednosti, na primjer, "1". Ovaj pristup osigurava da je direktorij sesije čist, ali očito previše opterećuje poslužitelj. Stoga je na proizvodnim sustavima session.gc_divisor prema zadanim postavkama postavljen na 1000, što znači da će se motor za prikupljanje smeća pokrenuti s vjerojatnošću od 1/1000. Ako eksperimentirate s ovim postavkama u vašoj datoteci php.ini, primijetit ćete da u gornjem slučaju, kada preglednik zatvori i izbriše sve svoje kolačiće, još neko vrijeme postoje stare sesije u direktoriju sesije. Ali to vas ne bi trebalo brinuti, jer kao što je već spomenuto, to ni na koji način ne utječe na sigurnost našeg mehanizma.

    Ažuriranje od 07.06.2013

    Sprječavanje zastoja skripti zbog blokiranja datoteke sesije

    U komentarima su pokrenuli pitanje zamrzavanja istovremeno pokrenutih skripti zbog blokiranja datoteke sesije (kao najsvjetlija opcija - duga anketa).

    Za početak napominjem da ovaj problem ne ovisi izravno o opterećenju poslužitelja ili broju korisnika. Naravno, što je više zahtjeva, to se skripte sporije izvode. Ali ovo je neizravna ovisnost. Problem se javlja samo unutar jedne sesije, kada poslužitelj primi nekoliko zahtjeva u ime jednog korisnika (npr. jedan od njih je duga anketa, a ostali su obični zahtjevi). Svaki zahtjev pokušava pristupiti istoj datoteci sesije, a ako prethodni zahtjev nije otključao datoteku, sljedeći će visjeti na čekanju.

    Kako bi blokiranje datoteka sesije bilo na minimumu, preporuča se zatvoriti sesiju pozivanjem funkcije session_write_close () odmah nakon što se izvedu sve radnje s varijablama sesije. U praksi to znači da ne biste trebali sve pohranjivati ​​u varijable sesije i pozivati ​​se na njih tijekom izvođenja skripte. A ako je potrebno pohraniti neke radne podatke u varijable sesije, pročitajte ih odmah na početku sesije, spremite ih u lokalne varijable za kasniju upotrebu i zatvorite sesiju (što znači zatvaranje sesije pomoću funkcije session_write_close, a ne uništavanje koristeći session_destroy).

    U našem primjeru to znači da odmah nakon otvaranja sesije, provjere njenog životnog vijeka i postojanja ovlaštenog korisnika, moramo pročitati i spremiti sve dodatne varijable sesije potrebne za aplikaciju (ako ih ima), a zatim zatvoriti sesiju pomoću session_write_close ( ) pozvati i nastaviti izvršavanje skripte, bilo da se radi o dugoj anketi ili običnom zahtjevu.

    Zaštita sesija od neovlaštene uporabe

    Zamislimo situaciju. Jedan od vaših korisnika ulovi trojanca koji opljačka kolačić preglednika (u kojem je pohranjena naša sesija) i pošalje ga na navedenu e-poštu. Napadač prima kolačić i koristi ga za krivotvorenje zahtjeva u ime našeg ovlaštenog korisnika. Poslužitelj uspješno prihvaća i obrađuje ovaj zahtjev kao da je došao od ovlaštenog korisnika. Ako se ne provede dodatna provjera IP adrese, takav napad će dovesti do uspješnog hakiranja korisničkog računa sa svim posljedicama koje iz toga proizlaze.

    Zašto je to moguće? Očito, jer su naziv i identifikator sesije uvijek isti tijekom cijelog životnog vijeka sesije, a ako primite te podatke, možete slobodno slati zahtjeve u ime drugog korisnika (naravno, unutar trajanja ove sesije). Možda ovo nije najčešća vrsta napada, ali u teoriji sve izgleda sasvim izvedivo, pogotovo s obzirom na to da takav trojanac ne treba niti administratorska prava da bi opljačkao kolačiće preglednika korisnika.

    Kako se možete obraniti od napada ove vrste? Opet, očito ograničavanjem životnog vijeka identifikatora sesije i povremenom promjenom identifikatora unutar jedne sesije. Također možemo promijeniti naziv sesije, potpuno izbrisati staru i kreirati novu sesiju, kopirajući sve varijable sesije iz stare u nju. Ali to ne utječe na bit pristupa, stoga ćemo se zbog jednostavnosti ograničiti samo na identifikator sesije.

    Jasno je da što je kraći životni vijek identifikatora sesije, to će napadač imati manje vremena za dobivanje i korištenje kolačića za krivotvorenje korisničkog zahtjeva. Idealno bi bilo da se za svaki zahtjev koristi novi identifikator, što će minimizirati mogućnost korištenja tuđe sesije. Ali razmotrit ćemo opći slučaj gdje je vrijeme za regeneraciju ID-a sesije postavljeno proizvoljno.

    (Izostavimo dio koda o kojem je već bilo riječi).

    Funkcija startSession ($ isUserActivity = true) (// Životni vijek ID-a sesije $ idLifetime = 60; ... if ($ idLifetime) (// Ako je životni vijek ID-a sesije postavljen, // provjerite vrijeme koje je proteklo od kreiranja sesije ili posljednja regeneracija // (vrijeme posljednjeg zahtjeva kada je varijabla početka ažurirana) if (isset ($ _ SESSION ["starttime"])) (if ($ t - $ _ SESSION ["starttime"]> = $ idLifetime) (// Vremenski ID sesije je istekao // Generirajte novi ID session_regenerate_id (true); $ _SESSION ["starttime"] = $ t;)) else (// Dolazimo ovdje ako je sesija upravo stvorena // Postavi vrijeme generiranja ID-a sesije u trenutnom trenutku $ _SESSION ["starttime"] = $ t;)) vrati true;)

    Dakle, prilikom kreiranja nove sesije (koja se događa kada se korisnik uspješno prijavi), postavljamo varijablu sesije starttime, koja za nas pohranjuje vrijeme posljednje generacije identifikatora sesije, na vrijednost jednaku trenutnom vremenu poslužitelja. Nadalje, u svakom zahtjevu provjeravamo je li prošlo dovoljno vremena (idLifetime) od posljednje generacije identifikatora, a ako je prošlo, generiramo novi. Dakle, ako u navedenom vijeku trajanja identifikatora napadač koji je primio kolačić ovlaštenog korisnika ne uspije ga upotrijebiti, poslužitelj će lažni zahtjev smatrati neovlaštenim, a napadač će biti odveden na stranicu za prijavu.

    Bilješka: Novi identifikator sesije ulazi u kolačić preglednika kada se pozove funkcija session_regenerate_id (), koja šalje novi kolačić, slično funkciji session_start (), tako da ne moramo sami ažurirati kolačiće.

    Ako želimo što bolje osigurati naše sesije, dovoljno je postaviti vijek trajanja identifikatora na jedan ili čak staviti funkciju session_regenerate_id () izvan zagrada i ukloniti sve provjere, što će dovesti do regeneracije identifikatora u svakom zahtjevu. (Nisam testirao utjecaj ovog pristupa na izvedbu i mogu samo reći da funkcija session_regenerate_id (true) u biti izvodi samo 4 radnje: generiranje novog identifikatora, stvaranje zaglavlja iz kolačića sesije, brisanje starog i stvaranje nove datoteke sesije).

    Lirska digresija: Ako se trojanac pokaže toliko pametnim da neće poslati kolačiće napadaču, već sam organizira slanje unaprijed pripremljenog lažnog zahtjeva odmah po primitku kolačića, gore opisana metoda najvjerojatnije neće moći zaštititi protiv takvog napada, jer između vremena kada trojanac primi kolačić i slanja lažnog, praktički neće biti razlike u zahtjevu, a postoji velika vjerojatnost da se ID sesije u ovom trenutku neće regenerirati.

    Mogućnost istovremenog rada u jednom pregledniku u ime više korisnika

    Posljednji zadatak koji bih želio razmotriti je mogućnost istovremenog rada u jednom pregledniku za nekoliko korisnika. Ova je značajka posebno korisna u fazi testiranja, kada trebate oponašati istovremeni rad korisnika, a preporučljivo je to učiniti u svom omiljenom pregledniku, a ne koristiti cijeli raspoloživi arsenal ili otvarati više instanci preglednika u "inkognito" " način rada.

    U našim prethodnim primjerima nismo eksplicitno postavili naziv sesije, pa je korišteno zadano PHP ime (PHPSESSID). To znači da su sve sesije koje smo do sada kreirali poslale kolačiće u preglednik pod imenom PHPSESSID. Očito, ako je naziv kolačića uvijek isti, onda ne postoji način unutar istog preglednika organizirati dvije sesije s istim imenom. Ali kada bismo za svakog korisnika koristili različit naziv sesije, problem bi bio riješen. Pa ćemo to učiniti.

    Funkcija startSession ($ isUserActivity = true, $ prefix = null) (... if (session_id ()) vrati true; // Ako je korisnički prefiks proslijeđen u parametrima, // postavite jedinstveni naziv sesije koji uključuje ovo prefiks, // inače postavite ime zajedničko svim korisnicima (na primjer, MYPROJECT) session_name ("MYPROJECT". ($ prefiks? "_". $ prefix: "")); ini_set ("session.cookie_lifetime", 0) ; if (! session_start ()) vrati false; ...)

    Sada ostaje samo osigurati da skripta za pozivanje prosljeđuje jedinstveni prefiks za svakog korisnika funkciji startSession (). To se može učiniti, na primjer, prosljeđivanjem prefiksa u GET/POST parametrima svakog zahtjeva ili putem dodatnog kolačića.

    Zaključak

    U zaključku, dat ću potpuni konačni kod naših funkcija za rad s PHP sesijama, uključujući sve gore navedene zadatke.

    Funkcija startSession ($ isUserActivity = true, $ prefix = null) ($ sessionLifetime = 300; $ idLifetime = 60; if (session_id ()) vrati true; session_name ("MYPROJECT". ($ Prefiks? "_". $ Prefiks: "")); ini_set ("session.cookie_lifetime", 0); if (! session_start ()) vrati false; $ t = vrijeme (); if ($ sessionLifetime) (if (isset ($ _ SESSION ["lastactivity") ] ) && $ t - $ _ SESSION ["lastactivity"]> = $ sessionLifetime) (destroySession (); vrati false;) else (if ($ isUserActivity) $ _SESSION ["lastactivity"] = $ t;)) if ($ isUserActivity) $ idLifetime ) (if (isset ($ _ SESSION ["starttime"])) (if ($ t - $ _ SESSION ["starttime"]> = $ idLifetime) (session_regenerate_id (true); $ _SESSION ["starttime"] = $ t; )) else ($ _SESSION ["starttime"] = $ t;)) vrati true;) funkcija destroySession () (if (id_session ()) (session_unset (); setcookie (session_name (), session_id () , vrijeme () -60 * 60 * 24); session_destroy ();))

    Nadamo se da će ovaj članak uštedjeti malo vremena onima koji se nikada nisu bavili sesijskim mehanizmom i dati dovoljno razumijevanja ovog mehanizma za one koji se tek počinju upoznavati s PHP-om.

    Sesije u PHP-u ili kako se podaci o korisniku ili kupcu koji je ušao na stranicu spremaju prilikom navigacije između stranica stranice bez većih poteškoća. Lekcija je vrlo važna. Relevantno za izradu 95% stranica.

    Što je sesija u php

    Sesije se koriste za pohranjivanje informacija o privremenim podacima (na primjer, da je korisnik ušao na stranicu) prilikom navigacije između stranica iste stranice. Kada koristite sesije, podaci se spremaju u privremene datoteke na poslužitelju.
    Najčešće se sesije (usput rečeno, također i kolačići) koriste pri izradi internetskih trgovina, foruma, oglasnih ploča, društvenih mreža, blogova i drugih resursa. Pogodnost sesijskog sustava sastoji se u pohranjivanju privremenih informacija prijavljenog korisnika/kupca, čiji su podaci u brzom pristupu određeno vrijeme. Sesija ima prirodni datum isteka - dok se preglednik ne zatvori. Ako zatvorite samo stranicu, onda kada otvorite stranicu, podaci o korisniku/kupcu će i dalje biti dostupni.

    Logika sesije

    Sesija (ili sesija) je vrsta privremene pohrane podataka. Odmah vas upozoravam da je vrijedno uštedjeti malu količinu podataka. Na primjer, prijava i lozinka korisnika koji se prijavljuje ili njegov serijski broj u bazi podataka.

    Primjer rada
    1. Korisnik upisuje korisničko ime i lozinku te ulazi na stranicu
    2. Podaci s prijavom i lozinkom spremaju se u sesiji jedne od stranica stranice:

    Datoteka index.php

    Početak_sesije (); // svaka datoteka u kojoj želite koristiti podatke o sesiji mora sadržavati naredbu "start session" na početku koda

    $login = "admin";
    $ lozinka = "prolazi";
    $ _SESSION ["login"] = $ prijava; // spremi varijablu koja sadrži prijavu
    $ _SESSION ["password"] = $ lozinka; // spremamo varijablu koja sadrži lozinku

    3. Kada odete na drugu stranicu stranice, bit će dostupni i ovi podaci:

    Datoteka primjer.php(ili bilo koja druga stranica)

    Echo "Vaša prijava". $ _ SESSION ["prijava"]; // će prikazati "Vaša prijava je admin", iako nismo zabilježili podatke na ovoj stranici!
    Vidite, jednostavno je!

    4. Ako želite izbrisati podatke sesije, dovoljno je:

    Datoteka primjer.php

    Početak_sesije (); // ponovno "pokreni sesiju".

    Poništeno ($ _ SESSION ["prijava"]); // ovako je varijabla neregistrirana ili "uništena"
    echo "Vaša prijava". $ _ SESSION ["prijava"]; // će prikazati "Vaša prijava". Budući da smo ga uništili u zadnjem redu, nema ni podataka.

    Session_destroy (); // uništiti sesiju. Svi podaci uključujući $_SESSION ["password"] su nestali. Kada se to zatraži, prikazat će se pogreška
    Općenito, takav prijenos je sličan POST metodi, ali više ne morate pisati puno nepotrebnog koda, a svi podaci koji se prenose sa stranice na stranicu pohranjuju se u privremene datoteke na poslužitelju. Opet, sesije bi trebale sadržavati male količine podataka, tako da su prikladne za pohranu korisničkog imena/lozinke, košarice za kupnju i drugih malih količina.

    Prosljeđivanje vrijednosti ili niza pomoću PHP sesije

    U sesiji možete napisati ne samo niz, već i niz podataka. Samo nemojte pretjerivati ​​s veličinom niza, jer će sve to utjecati na performanse i zauzeti prostor na poslužitelju.

    Ponovno koristimo određenu početnu stranicu index.php

    Početak_sesije ();

    $ r = niz ("jedan", "dva", "tri");

    $ _SESSION ["arr"] = $ r;

    Na stranicu na kojoj je sve prikazano
    Podatke smo spremili u sesiji i slijedite link na drugu stranicu, gdje ćemo prikazati sve podatke.

    Primatelj datoteke, stranica test.php gdje otvaramo niz

    Početak_sesije ();
    print_r ($ _ SESSION ["arr"]);
    // će ispisati
    /*
    Niz
    => jedan
    => dva
    => tri
    */
    ?>
    Možda biste željeli nadopuniti vodič o. Općenito, sve bi trebalo biti jasno.

    Ostale funkcije za rad sa sesijama

    session_unregister (niz)- sesija zaboravlja vrijednost navedene globalne varijable;
    session_destroy ()- sesija je uništena (na primjer, ako je korisnik napustio sustav pritiskom na gumb za odjavu);
    session_set_cookie_params (int životni vijek [, put niza [, domena niza]])- pomoću ove funkcije možete postaviti koliko će dugo sesija živjeti postavljanjem unix_timestamp, koji određuje vrijeme smrti sesije.

    Popis funkcija za rad sa sesijama (session) u php
    session_cache_expire - Vraća istek trenutne predmemorije
    session_cache_limiter - Dobijte i/ili postavite trenutno ograničenje predmemorije
    session_commit - alias za session_write_close ()
    session_decode - dekodira podatke sesije iz niza
    session_destroy - Uništava sve podatke registrirane za sesiju
    session_encode - šifrira podatke trenutne sesije kao niz
    session_get_cookie_params - Dobivanje parametara kolačića sesije
    session_id - dobiva i/ili postavlja ID trenutne sesije
    session_is_registered - određuje je li varijabla registrirana u sesiji
    session_module_name - Nabavite i/ili instalirajte modul za trenutnu sesiju
    session_name - dobiva i/ili postavlja naziv trenutne sesije
    session_regenerate_id - Modificira trenutni ID sesije s novim generiranim
    session_register - registrira jednu ili više varijabli za trenutnu sesiju
    session_save_path - dobiva i/ili postavlja put za spremanje trenutne sesije
    session_set_cookie_params - postavlja parametre kolačića sesije
    session_set_save_handler - postavlja funkcije pohrane sesije na razini korisnika
    session_start - inicijalizira podatke sesije
    session_unregister - Poništava registraciju varijable iz trenutne sesije
    session_unset - Otpušta sve varijable sesije
    session_write_close - Zapisuje podatke o sesiji i kraj sesije

    Primjeri sesija

    Brojač prikaza stranica tijekom sesije. Ilustrativan primjer rada. Međutim, nakon zatvaranja preglednika, odbrojavanje će početi ispočetka.

    Brojač posjeta jednoj stranici unutar jedne sesije

    // Jednostavan primjer korištenja sesija bez kolačića.
    session_name ("test");
    početak_sesije ();
    $ _SESSION ["count"] = @ $ _ SESSION ["count"] + 1;
    ?>

    Brojač


    U trenutnoj sesiji rada s preglednikom otvorili ste ovu stranicu
    vrijeme (s).
    Zatvorite svoj preglednik da poništite ovaj brojač.
    Kliknite ovdje za osvježavanje stranice!
    Sa svakim prijelazom, brojač će se povećati za 1)

    Hvala na pažnji! Sretno u vašim nastojanjima!

    Prije nego što definiramo pojam "session", pogledajmo malo pozadinu, zašto je uopće bilo potrebe za sesijama, razmotrimo jednu značajku HTTP protokola.

    Jedna od glavnih značajki HTTP protokola je da ne obvezuje poslužitelj da pohranjuje podatke o klijentu između zahtjeva, odnosno da identificira klijenta. Ovo je takozvani protokol bez državljanstva. Komunikacija između klijenta i poslužitelja završava čim se završi obrada trenutnog zahtjeva. Pretpostavlja se da je svaki novi zahtjev poslužitelju potpuno jedinstven i neovisan, čak i ako je ponovno poslan iz istog izvora.

    Što ako ostavimo prirodu HTTP protokola bez državljanstva i ne provjeravamo autentičnost korisnika? Stanja sesije mogu se jednostavno izostaviti ako vaša stranica sadrži statične (anonimizirane) informacije, kao što je članak vijesti sastavljen od teksta i slika. U takvom kontekstu potpuno je nepotrebno povezivati ​​više zahtjeva s istim korisnikom. Uostalom, sadržaj članka se neće promijeniti ni na koji način, bilo da se radi o deset zahtjeva s jednog uređaja ili deset zahtjeva različitih ljudi s različitih uređaja.

    Ali čim ćemo prenijeti osobne podatke na poslužitelj, moramo se nekako pobrinuti da poslužitelj poveže sve naše zahtjeve s nama, te da u budućnosti ispravno identificira sve zahtjeve koji odlaze od nas. Ako se to ne učini, tada ćemo sa svakim novim zahtjevom biti prisiljeni ponovno prenijeti potrebne osobne podatke. Na primjer, prijava za unos vašeg osobnog računa na web-mjestu, ili podaci kao što su ime, adresa za dostavu, prilikom kupnje u internetskoj trgovini.

    U takvim situacijama, kada je potrebno personalizirati zahtjeve jednog klijenta, koristit ćemo sesije.

    Sesija (sjednica) je određeno vremensko razdoblje unutar kojeg web aplikacija može odrediti sve zahtjeve jednog klijenta.

    Kada klijent prvi put prenese osobne podatke u zahtjevu, na poslužitelju se kreira nova sesija za tog klijenta. Tijekom trajanja sesije, svi zahtjevi ovog klijenta bit će jedinstveno prepoznati i povezani s njim. Nakon tog vremena komunikacija s klijentom će se izgubiti, a sljedeći zahtjev od njega bit će obrađen kao apsolutno jedinstven, ni na koji način povezan s prethodnim.

    Na primjer, prilikom kupnje u online trgovini, osobni podaci korisnika spremaju se u sesiji dok surfa po stranici. To su odabrani artikli u košarici, adresa za dostavu, kontakt podaci i tako dalje.

    Sada da vidimo kako to možemo tehnički implementirati. Općenito, postoji nekoliko tehnika za upravljanje klijentskim sesijama, njihov broj i način implementacije uvelike ovise o web platformi ili tehnologiji koja se izvodi na poslužitelju. U ovom vodiču ćemo pokriti sljedeće:

    1. skrivena polja obrasca
    2. kolačići
    3. sjednica (sjednica, stanje sjednice)

    Pokušajmo ih implementirati pomoću ASP.NET platforme. Pogledajmo na brzinu prva dva mehanizma, a posebnu pažnju posvetimo trećem, kao pouzdanijem, praktičnijem i sigurnijem.

    Skrivena polja obrasca

    Suština ovog pristupa je u tome da navigaciju web stranicama pružamo pomoću standardnih html obrazaca. A uz svaki sljedeći zahtjev spremamo podatke iz prethodnog u skrivena polja na obrascu. Na primjer:

    @using (Html.BeginForm ("Forms2", "Home", FormMethod.Post)) (

    Naručivanje jela

    }
    javni ActionResult Forms2 () (ViewBag.UserName = Request.Form ["userName"]; vrati View ();)
    @using (Html.BeginForm ("Forms3", "Home", FormMethod.Post)) (

    @ ($ "Dobar dan (ViewBag.UserName)! Što ćete naručiti?")

    }

    U ovom primjeru dobivamo korisničko ime na prvom html-obrascu. Dalje u kontroleru u metodi Obrasci2 () ovu vrijednost dohvaćamo iz zbirke Oblik i proslijediti ga pogledu kroz objekt ViewBag... Ovaj prikaz generira kod za novi obrazac i pohranjuje ime korisnika u skriveno polje. Tako će se vrijednost korisničkog imena prenijeti u treći obrazac zajedno s dodatnim podacima - vrijednosti polja s imenom "naziv hrane"... itd.

    Pogledajmo značajke ovog pristupa. Prednosti praktički nema, osim što se ova tehnika može vrlo brzo implementirati. Ali opet, drugi pristupi se također mogu vrlo brzo implementirati. Ali postoje nedostaci, i to prilično značajni:


    Kolačići

    javni ActionResult Cookies2 () (HttpCookie cookie = novi HttpCookie ("userName", HttpUtility.UrlEncode (Request.Form ["userName"])); cookie.Expires = DateTime.UtcNow.AddHours (1); Response.Cookies.Add. kolačić); vrati View ();)
    @using (Html.BeginForm ("Cookies3", "Home", FormMethod.Post)) (

    @ ($ "Pozdrav (HttpUtility.UrlDecode (Request.Cookies [" userName "] ?. Vrijednost))! Što ćete naručiti?")

    }

    U ovom pristupu ne pohranjujemo podatke o sesiji izravno na obrascu, već koristimo standardni mehanizam kolačića između klijenta i poslužitelja. Svi korisnički podaci pohranjeni su u kolačićima.

    Prilikom odabira ovakvog pristupa, opet, glavni problem ostaje sigurnost naših podataka koje prenosimo na server – lako ih je zamijeniti ili ukrasti, jasno je. Također, ako je prihvaćanje kolačića sa stranica onemogućeno u postavkama privatnosti preglednika klijenta, tada ova opcija za održavanje sesije uopće neće raditi.

    Stoga se vrlo ne preporučuje prijenos važnih i tajnih podataka na prva dva načina, kao što su prijave, lozinke, brojevi kartica i računa, podaci iz putovnice, mjesto stanovanja itd.

    Mehanizam upravljanja sesijom na strani poslužitelja (Session, SessionState)

    Pogledajmo kako mehanizam sesije radi sa strane poslužitelja i sa strane klijenta.

    Uz standardne postavke rada stanja sesije, tzv. kolačić sesije Algoritam je sljedeći:

    1. Za apsolutno svaki novi zahtjev poslužitelju (nije važno jesu li različiti klijenti ili jedan) ASP.NET generira jedinstveni identifikator sesije.
      Identifikator sesije je nasumično generirani broj kodiran posebnim algoritmom u niz od 24 znaka. Niz se sastoji od malih slova od A do Z, kao i brojeva od 0 do 5. Primjer identifikatora je hjnyuijl1pam3vox2h5i41in
    2. Ako se tijekom trenutnog zahtjeva klijentovi podaci NE spremaju za daljnji rad s njima, tada završava životni vijek sesije ovog klijenta (u stvari ne počinje). U tom slučaju, prethodno generirani identifikator sesije postaje nevažeći (jer nije korišten). Kao odgovor na takav zahtjev, klijent ne dobiva ništa što bi ga povezalo s novom sesijom.
    3. Ako su klijentski podaci (na primjer, ime, adresa za dostavu) pohranjeni na poslužitelju, ASP.NET povezuje pohranjene podatke s prethodno generiranim ID-om sesije. Zatim se kreira poseban kolačić sesije, u koji se također upisuje ovaj identifikator. Ovaj kolačić se dodaje kao odgovor na zahtjev i pohranjuje u klijentov preglednik. Tako se stvara veza između klijenta i njegovih personaliziranih podataka na poslužitelju. Za ovog klijenta stvorena je nova sesija.
    4. Svakim sljedećim zahtjevom klijent šalje poslužitelju osobni identifikator sesije putem kolačića. Poslužitelj odgovara identifikatorima i "prepoznaje" klijenta unutar trenutne sesije.
    5. Sve dok klijent prenosi svoj osobni ključ, sesija se smatra aktivnom. Sesija se može završiti iz različitih razloga, na primjer, ručno na strani poslužitelja ili nakon određenog zadanog vremena (timeout).

    Prijeđimo s teorije na praksu. Programirajmo ovaj algoritam i vidimo kako radi. Za to koristimo posebnu klasu HttpSessionState. Kada radite u kontroleru, možete koristiti svojstvo HttpContext.Session. Rad sa sesijom vrlo je jednostavan, kao i sa svakom NameValueCollection:

    Sesija ["userName"] = Request.Form ["userName"]; bool isSessionNew = Sesija.IsNewSession; string sessionId = Sesija.SessionID;

    U ovom dijelu koda upisujemo korisničko ime u stanje sesije. Ovo ime preuzimamo iz html obrasca koji nam je poslao. Dodatno, kroz svojstva saznajemo je li ova sesija upravo stvorena, odnosno u okviru trenutnog zahtjeva (ako je tako, tada će vrijednost svojstva IsNewSession biti istinita), te jedinstveni identifikator sesije . Nakon obrade zahtjeva, ovaj identifikator će se automatski zabilježiti u kolačić sesije (ako već nije) i poslan u odgovoru klijentu.

    U klijentovom pregledniku možete vidjeti odgovarajući kolačić i identifikator njegove sesije:

    Na sljedeći zahtjev ovog klijenta, pročitajmo njegov prethodno spremljeni naziv iz sesije. Također ćemo prisilno prekinuti sjednicu. Rad s ovim klijentom je završen, npr. svi podaci su obrađeni i roba poslana.

    String korisničko ime = sesija ["userName"]. ToString (); // obrada zahtjeva ... Session.Abandon ();

    Kao što vidite, rad sa sesijama je vrlo jednostavan i praktičan. Većina procesa povezanih s obradom sesije odvija se automatski u pozadini. Naravno, programer može intervenirati u bilo kojoj fazi obrade sesije i napraviti vlastite prilagodbe.

    Pogledajmo najzanimljivija svojstva i metode klase HttpSessionState koje se najčešće koriste u radu:

    Artikal- vraća stavku podataka prema njezinom indeksu
    Artikal- vraća stavku po ključu
    Ukloni (indeks)- uklanja stavku podataka prema njezinom indeksu
    Ukloni (ključ)- briše stavku po ključu
    Čisto ()- briše sve podatke
    Računati- vraća ukupan broj stavki podataka za trenutnu sesiju
    napustiti ()- prisilno prekinuti sjednicu
    ID sesije- vraća identifikator trenutne sesije
    IsNewSession- vraća true ako je sesija stvorena unutar trenutnog zahtjeva
    Pauza- vraća dopušteni broj minuta između zahtjeva prije nego što sesija završi zbog isteka (prema zadanim postavkama, 20 minuta)

    Postavke za sesiju možete promijeniti bilo programski u kodu putem članova klase HttpSessionState ili putem konfiguracije aplikacije (). Na primjer:

    U gornjoj smo konfiguraciji naveli da će timeout sesije biti 40 minuta, podaci o sesiji korisnika će biti pohranjeni u RAM, koristit će se kolačići sesije, a također smo promijenili standardni naziv takvog kolačića u naš vlastiti.

    I još jedna važna napomena u smislu sigurnosti. Kada završite sesiju korisnika metodom Session.Abandon (); kolačić sesije koji pohranjuje identifikator sesije SessionId se ne briše u pregledniku korisnika. To znači da ako korisnik započne novu sesiju u bliskoj budućnosti bez zatvaranja preglednika, tada će isti SessionId biti dodijeljen njegovoj novoj sesiji. Preporučljivo je svakoj novoj sesiji uvijek dodijeliti novi jedinstveni identifikator, za to moramo ručno izbrisati kolačić sesije nakon što se sesija zatvori:

    Session.Clear (); // brisanje sesije Session.Abandon (); // otkazati sesiju // ručno obrisati kolačiće poput ovog Response.Cookies.Add (novi HttpCookie ("ASP.NET_SessionId", "")); // ili skratiti životni vijek Response.Cookies ["ASP.NET_SessionId"]. Expires = DateTime.Now.AddYears (-30); //ASP.NET_SessionId je zadani naziv za kolačić sesije, možete imati svoj vlastiti

    Ovako se stanje korisničke sesije prati na ASP.NET platformi, koristeći sesije. Ovaj pristup je standardni i preporučljiv za korištenje kada je potrebno pohraniti podatke o korisniku i identificirati ga između zahtjeva poslužitelju.

    Koristeći PHP sesiju, poslužitelj vas identificira i omogućuje vam izvođenje potrebnih operacija: mijenjanje informacija na raznim web stranicama, dodavanje novih informacija itd. Nakon završetka rada na stranici brišete trenutnu sesiju klikom na gumb "Odjava":

    Što je PHP sesija?

    PHP sesija je način pohranjivanja informacija u varijablama sesije koje se mogu koristiti za provjeru autentičnosti na više web stranica. Za razliku od kolačića, informacije o sesiji ne pohranjuju se na korisnikovo računalo. Umjesto toga, sesija stvara datoteku na poslužitelju u privremenom direktoriju.

    Ove informacije, pohranjene tijekom cijele sesije, dostupne su svim web stranicama izvora. Na poslužitelju, lokacija privremene datoteke određena je parametrom session.save_path u konfiguracijskoj datoteci php.ini.

    Prilikom izrade PHP sesije rade se sljedeće tri stvari:

    • Kada se kreira sesija, PHP generira jedinstveni identifikator, koji je nasumični niz od 32 heksadecimalna broja. Identifikator životnog vijeka PHP sesije izgleda otprilike ovako: 9c8foj87c3jj973actop1re472e8774;
    • Poslužitelj šalje kolačić pod nazivom PHPSESSID na korisničko računalo za pohranu jedinstvenog niza identifikatora sesije;
    • Poslužitelj generira datoteku u navedenom privremenom direktoriju koja sadrži naziv jedinstvenog identifikatora sesije s prefiksom sess _g. sess_9c8foj87c3jj973actop1re472e8774.

    Ove postavke pomažu PHP skripti da izdvoji vrijednosti varijable sesije iz datoteke. Na strani klijenta, PHPSESSID sadrži identifikator sesije. Potvrđuje naziv datoteke koju treba tražiti u određenom direktoriju na strani poslužitelja, iz kojeg se varijable sesije mogu dohvatiti i koristiti za provjeru valjanosti.

    Korisnik može prekinuti sesiju klikom na gumb za odjavu, koji poziva funkciju session_destroy (). Kada korisnik zatvori preglednik, PHP sesija se automatski zatvara. U suprotnom, poslužitelj će prekinuti sesiju nakon navedenog vremenskog razdoblja.

    Sintaksa sesije u PHP-u

    Tijekom autorizacije PHP sesije, kreira se pomoću funkcije session_start () i briše pomoću funkcije session_destroy (). PHP globalna varijabla, poznata kao $ _SESSION, koristi se za postavljanje vrijednosti varijabli sesije. Možete resetirati sve vrijednosti postavljene za varijable sesije pomoću funkcije session_unset ().

    Operacije sesije

    Pogledat ćemo sljedeće operacije koristeći PHP sesiju, kao i primjere.

    • Pokretanje PHP sesije i postavljanje njenih varijabli sesije: nova PHP sesija se pokreće pomoću funkcije session_start (). Nakon što je sesija stvorena, možete postaviti vrijednosti njenih varijabli sesije pomoću $_SESSION. Postavili smo vrijednosti za varijable " ID korisnika” — “php_user"i" zaporka” — “tutoriali”:

    PHP sesije - stvaranje PHP sesija je započela i varijable sesije su postavljene! ";?>

    Rezultat: kao rezultat pokretanja gornjeg PHP koda na poslužitelju, prikazat će se sljedeća poruka:


    • Dobivanje vrijednosti varijable PHP sesije: Možete dobiti vrijednosti varijabli koje smo postavili tijekom posljednje sesije prijave na PHP. Kada otvorimo PHP sesiju na početku svake stranice ( session_start ()), treba navesti kod u nastavku. Ove vrijednosti dohvaćamo i prikazujemo pomoću globalne varijable $_SESSION:

    PHP sesija - dobivanje vrijednosti
    "; echo" Lozinka je ". $ _SESSION [" lozinka "].". ";?>

    Rezultat: Kada pokrenemo gornji PHP kod na poslužitelju, kao rezultat dobivamo sljedeću poruku. Prikazuju se vrijednosti varijabli sesije koje smo postavili ranije nakon kreiranja PHP sesije.


    • Ažuriranje vrijednosti varijable PHP sesije: Tijekom sesije možete ažurirati vrijednosti njenih varijabli. Prvo, moramo otvoriti PHP sesiju na početku svake stranice ( session_start ()). U kodu ispod ažuriramo vrijednosti varijabli " ID korisnika” — “novi_php_user"i" zaporka” — “obrazovanje”.

    Možete ispisati niz varijabli sesije i njihovih vrijednosti pomoću funkcije print_r ($ _SESSION) kao što je prikazano u nastavku:

    PHP sesija - mijenjanje vrijednosti
    "; print_r ($ _ SESSION);?>

    Rezultat: kada pokrenemo gornji PHP kod na poslužitelju, dobivamo sljedeću poruku. Sadržavat će niz varijabli sesije s njihovim novim vrijednostima:


    • Brisanje PHP sesije i resetiranje svih vrijednosti varijabli sesije: PHP sesiju možete resetirati pomoću funkcije session_unset () i izbrisati trenutnu sesiju pomoću funkcije session_destroy ():

    PHP sesija - brisanje
    PHP sesija i sve varijable sesije uspješno su izbrisane!

    "; ?>

    Rezultat: Kada pokrenemo gornji PHP kod na web poslužitelju, ispisat će sljedeću poruku:


    Zaključak

    U ovom članku govorili smo o raznim funkcijama za rad s PHP sesijama, njihovoj sintaksi. Za razliku od kolačića, informacije o sesiji pohranjuju se na strani poslužitelja. To čini PHP sesije pouzdanijim.

    Vrhunski povezani članci