Cum se configurează smartphone-uri și PC-uri. Portal informativ
  • Acasă
  • OS
  • Capcanele utilizării sesiunilor în PHP. Utilizarea sesiunilor - Lucrul cu sesiunile PHP

Capcanele utilizării sesiunilor în PHP. Utilizarea sesiunilor - Lucrul cu sesiunile PHP

Serverul web nu menține o conexiune persistentă la client, iar fiecare solicitare este tratată ca una nouă, fără nicio conexiune cu cele anterioare.
Adică nu puteți urmări solicitările de la același vizitator și nici nu puteți salva variabile pentru el între vizualizările paginilor separate. Sesiunile au fost inventate pentru a rezolva aceste două probleme.
De fapt, sesiunile, pe scurt, este un mecanism care vă permite să identificați unic un browser și să creeze un fișier pentru acest browser pe server, care stochează variabilele de sesiune.

Nu voi descrie în detaliu necesitatea unui astfel de mecanism. Acestea sunt astfel de cazuri de manuale precum un coș de cumpărături într-un magazin electronic, autorizare, precum și probleme nu în totalitate banale, cum ar fi, de exemplu, protejarea părților interactive ale site-ului de spam.

În principiu, este destul de ușor să-ți faci propriul analog de sesiuni, nu la fel de funcțional ca PHP-ul încorporat, dar similar în esență. Pe cookie-uri și baza de date.
Când solicităm un script, ne uităm să vedem dacă a sosit un cookie cu un nume specific. Dacă nu există cookie, setați-l și scrieți o nouă linie cu datele utilizatorului în baza de date. Dacă există un cookie, atunci citim din baza de date. Cu încă o solicitare, ștergem înregistrările vechi din baza de date, iar acum avem pregătit un mecanism de sesiune. Nu este deloc greu. Dar există câteva nuanțe care fac de preferat să se utilizeze mecanismul de sesiune încorporat.

Dacă numai primul este activat, atunci la începutul sesiunii (la fiecare apel session_start ()) este instalat un cookie pentru client. Browserul returnează corect acest cookie la fiecare cerere următoare, iar PHP are un identificator de sesiune. Problemele încep dacă browserul nu returnează cookie-uri. În acest caz, PHP va începe întotdeauna o nouă sesiune fără a primi cookie-uri cu un identificator, iar mecanismul nu va funcționa.

Dacă doar al doilea este activat, atunci cookie-ul nu este setat. Și ceea ce se întâmplă este, de dragul căruia, practic, de fapt, merită să utilizați mecanismul de sesiune încorporat. După ce scriptul își face treaba și pagina este complet formată, PHP se uită la toate și adaugă un ID de sesiune la fiecare link și la fiecare formular. Arata cam asa:
Index se transformă în
Index
iar la formulare se adaugă un câmp ascuns

Iar browserul, când dai clic pe orice link, sau când dai click pe un buton din formular, va trimite în cerere variabila de care avem nevoie - identificatorul de sesiune!
Din motive evidente, ID-ul este adăugat doar la link-urile relative.

Teoretic, în sesiunile noastre de casă pe cookie-uri și o bază de date, puteți atribui manual transferul de id-ul tuturor link-urilor - și apoi propriile noastre sesiuni vor funcționa independent de cookie-uri. Dar, vezi, e mai plăcut când altcineva face treaba asta? ;-)

Ambele opțiuni sunt activate implicit în versiunile recente de PHP. Cum gestionează PHP asta? Cook este mereu expus. Și linkurile sunt completate automat doar dacă PHP nu găsește un cookie cu un ID de sesiune. Când un utilizator vizitează site-ul pentru prima dată în timpul acestei sesiuni, el primește un cookie și sunt adăugate link-uri. La următoarea solicitare, dacă cookie-urile sunt acceptate, PHP vede cookie-ul și nu mai completează link-urile. Dacă cookie-urile nu funcționează, atunci PHP continuă să adauge corect id-ul la link-uri și sesiunea nu se pierde.
Utilizatorii care funcționează cookie-uri vor vedea linkul lung cu id-ul o singură dată.

Fuh. Odată ce transferul identificatorului s-a încheiat.
Acum rămâne să legați un fișier cu date de pe partea serverului.
PHP va face asta pentru noi. E suficient doar să scrii
sesiune_start ();
$ _SESSION ["test"] = "Bună lume!" ;

Și PHP va scrie variabila de test în fișierul asociat cu această sesiune.
Există un punct foarte important aici.
Matrice $ _SESIUNE- special.
În el, de fapt, sunt variabilele pe care vrem să le punem la dispoziție în diverse scripturi.
Pentru a plasa o variabilă într-o sesiune, trebuie doar să o atribuiți unui element al matricei $ _SESSION.
Pentru a-și obține valoarea, este suficient să ne referim la același element. Un exemplu va fi mai jos.

Colectarea gunoiului - PHP este, de asemenea, implicat în eliminarea fișierelor învechite. La fel și codificarea datelor și o grămadă de alte lucruri necesare. Ca urmare a acestei îngrijiri, lucrul cu ședințe este foarte ușor.
Iată-ne, de fapt, și ajungem la exemplul muncii de sesiuni.
Exemplul este foarte mic:
sesiune_start ();

ecou „Ați actualizat această pagină”... $ _SESSION [„contor”] ++. " o singura data. " ;
ecou"
Actualizați ";
?>

Verificăm dacă avem o variabilă contor în sesiune, dacă nu, atunci o creăm cu o valoare de 0, apoi scoatem valoarea acesteia și o creștem cu unu. Valoarea crescută va fi scrisă în sesiune, iar data viitoare când scriptul este apelat, variabila va avea valoarea 1 și așa mai departe.
Totul este foarte simplu.

Pentru a avea acces la variabilele de sesiune din orice pagină a site-ului, trebuie să scrieți NUMAI O RANDĂ (!) la începutul FIECĂRUI fișier în care avem nevoie de sesiuni:
sesiune_start ();
Și apoi faceți referire la elementele matricei $ _SESSION. De exemplu, o verificare de autorizare ar arăta cam așa:
sesiune_start ();
dacă ($ _SESSION [„autorizat”]<> 1 ) {
antet ("Locație: /auth.php");
Ieșire;
}

Eliminarea variabilelor dintr-o sesiune.
Dacă aveți register_globals = off, atunci scrieți
dezactivat ($ _ SESSION ["var"]);
Dacă nu, atunci lângă Trebuie să scriu cu ea
session_unregister ("var");

Cele mai frecvente erori pe care PHP le dă atunci când încearcă să lucreze cu sesiuni sunt:
Doi dintre ei,
Avertisment: nu se poate trimite cookie-ul de sesiune - anteturile au fost deja trimise
Avertisment: nu se poate trimite limitatorul de cache de sesiune - anteturile deja au fost trimise

cauzată de același motiv, soluția este descrisă în acest fapt
Al treilea,
Avertisment: deschidere (/ tmp \ sess_SID, O_RDWR) a eșuat: nu există un astfel de fișier sau director (2) în full_script_path pe numărul de linie(anterior ea arăta ca Avertisment: Nu s-au putut scrie datele de sesiune (fișiere). Vă rugăm să verificați dacă setarea curentă a session.save_path este corectă (/ tmp)),
dacă este tradus din engleză, explică problema în detaliu: calea specificată în php.ini către directorul în care sunt scrise fișierele de sesiune nu este disponibilă. Această eroare este cel mai ușor de remediat. Doar scrieți un director care există și care poate fi scris, de exemplu,
session.save_path = c: \ windows \ temp
Și nu uitați să reporniți Apache-ul după aceea.

După cum se dovedește, inteligența umană nu are limite și, prin urmare, trebuie să explic:
al treilea mesaj de eroare (directorul nu poate fi găsit) va conduce la primele două, deoarece mesajul de eroare este trimis în browser și nu puteți folosi antete după el. Prin urmare, nu vă grăbiți să căutați o concluzie prematură, ci mai întâi scrieți calea corectă!

Următoarea problemă cea mai frecventă atunci când aveți de-a face cu sesiuni este moștenirea grea a register_globals. NU dați variabilelor de script aceleași nume ca și indicilor matricei $ _SESSION!
Cu register_globals = on, valorile se vor suprascrie reciproc și vei fi confuz.
Și dacă register_globals = off, va apărea o altă eroare: „Scriptul tău se bazează posibil pe un efect secundar de sesiune care a existat până la PHP 4.2.3.” ... Pentru a scăpa de el, trebuie să inițializați întotdeauna variabilele înainte de utilizare (sau cel puțin să verificați existența) și să nu dați nume variabilelor globale care se potrivesc cu indicii matricei $ _SESSION.

Dacă nu funcționează, dar nici nu sunt afișate mesaje, atunci adăugați două linii chiar la începutul scriptului care sunt responsabile pentru afișarea TOATE erorile pe ecran - este foarte posibil să existe erori, dar pur și simplu nu vedeți lor.
ini_set („erori de afișare”, 1);
raportare_erori (E_ALL);

sau vedeți erorile în error_log. În general, subiectul afișării mesajelor de eroare depășește domeniul de aplicare al acestui articol, așa că asigurați-vă că cel puțin le puteți vedea. Puteți citi puțin mai multe detalii despre depanare în această secțiune.

Dacă sunteți sigur că nu există erori, dar exemplul dat oricum nu funcționează, atunci este posibil ca PHP să nu activeze transferul de id-ul prin url, iar cookie-urile din anumite motive nu funcționează.
Vezi ce ai cu cookie-urile.
În general, dacă sesiunile dvs. „nu funcționează”, atunci încercați mai întâi să transferați identificatorul de sesiune manual, adică să faceți un link și să îi atribuiți un identificator:
sesiune_start ();
if (! isset ($ _ SESSION ["contor"])) $ _SESSION ["contor"] = 0;
ecou „Ați actualizat această pagină”... $ _SESSION [„contor”] ++. " o singura data.

Actualizați ";
?>

Când faceți acest lucru, asigurați-vă că directiva session.use_only_cookies nu este activată, ceea ce împiedică PHP să accepte un ID de sesiune dacă acesta a fost transmis printr-un URL.

Dacă acest exemplu nu funcționează, atunci problema este fie în banal greșeli de tipar(jumătate din „problemele” cu sesiunile provin dintr-un nume de variabilă scris greșit), sau într-o versiune prea veche de PHP: suportul pentru sesiuni a apărut în versiunea 4.0, iar matricea $ _SESIUNE- în 4.1 (utilizat anterior $ HTTP_SESSION_VARS).
Dacă funcționează, atunci problema este în cookie-uri. Urmăriți ce fel de cookie îl pune serverul în browser, dacă acesta îl returnează. Căutarea este foarte utilă în timp ce se uită la schimburile de antet HTTP dintre browser și server.
Explicarea modului în care funcționează cookie-urile depășește domeniul de aplicare al acestui text deja prea mare, dar cel puțin asigurați-vă că serverul trimite cookie-ul cu identificatorul, iar browserul revine. Și în timp ce identificatorii coincid unul cu celălalt =)
Setarea cookie-ului ar trebui să arate ca
Set-Cookie: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6;
sau cum
Set-Cookie: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6; cale = /
(dacă solicitați un script care nu este din directorul rădăcină)
Răspunsul serverului ar trebui să arate ca
Cookie: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6
sau
Cookie: PHPSESSID = prlgdfbvlg5fbsbshch6hj0cq6; b = b
dacă browserul returnează alte module cookie în afară de ID-ul sesiunii.

Dacă browserul nu returnează module cookie, verificați dacă modulele cookie funcționează.
Asigurați-vă că domeniul pe care îl accesați are un nume normal (care are cel puțin un punct și nu conține caractere interzise, ​​cum ar fi caractere de subliniere) și ștergeți memoria cache a browserului - acestea sunt două motive principale pentru care cookie-urile ar putea să nu funcționeze.

Dacă exemplul de aici funcționează, dar propriul cod nu funcționează, atunci problema este evident că nu se află în sesiuni, ci în algoritm. Căutați unde ați pierdut variabila, transferați exemplul de aici pas cu pas, depanați scriptul.

O altă problemă poate apărea dacă utilizați redirecționarea antetului sau navigarea JavaScript.
Faptul este că PHP atașează automat identificatorul de sesiune numai la linkurile din formular
, dar nu face acest lucru pentru anteturi, javascript, metaetichete.
Prin urmare, trebuie să adăugați identificatorul manual, de exemplu, astfel:
antet ("Locație: /script.php?". session_name (). "=". session_id ());

De asemenea, foarte rar și nu este complet clar de unde vine problema, problema este că setarea session.save_handler are o altă valoare decât fișierele. Dacă nu este cazul, corectați-l.

Siguranță
Securitatea sesiunii este un subiect vast. Prin urmare, mă voi concentra pe câteva puncte principale.
Cel mai manual lucru este să nu treci identificatorul prin bara de adrese. Acest lucru este scris chiar și în php.ini, dar acest lucru limitează funcționalitatea sesiunilor. Dacă decideți să urmați acest sfat, atunci pe lângă session.use_trans_sid = 0, nu uitați session.use_only_cookies = 1
Este recomandabil să legați sesiunea la o adresă IP: în acest fel, dacă identificatorul este furat, răufăcătorul tot nu îl va putea folosi în majoritatea cazurilor.
Este recomandat să folosiți directiva session.save_path, cu ajutorul căreia vă puteți seta propriul director pentru salvarea fișierelor de sesiune. Acest lucru este mai sigur decât atunci când sunt stocate în directorul temporar partajat implicit al serverului.

Informații suplimentare:

  • Pe lângă cookie-uri, mecanismul de sesiune trimite și anteturi care interzic stocarea în cache a paginii (același limitator de cache). Pentru html, acest lucru este corect și necesar. Dar când încercați să trimiteți un fișier cu un script care verifică autorizarea, Internet Explorer refuză să-l descarce. Este din cauza acestui titlu. Apel
    session_cache_limiter ("privat");
    trebuie să rezolve problema înainte de a începe sesiunea.
  • Destul de ciudat, dar în matrice $ _SESIUNE nu poți folosi indici numerici - $ _SESSION [1], $ _SESSION ["10"]- sesiunile nu vor funcționa.
  • Undeva între 4.2 și 5.0 nu a fost posibil să setați session.use_trans_sid cu ini_set ()... Începând de la 5.0 este deja posibil din nou.
  • Înainte de versiunea 4.3.3, cookie-ul PHP trimitea cookie-ul numai dacă solicitarea nu conținea un identificator la începutul sesiunii. Acum cookie-ul este trimis la fiecare apel session_start ()

    Un exemplu de autorizare folosind sesiuni
    Să ilustrăm toate cele de mai sus cu un mic exemplu:
    să creăm fișierul auth.php:
    if (isset ($ _ POST ["nume_auth"]))
    {
    $ sql = „SELECT * FROM users WHERE nume =? S”;
    $ row = $ db -> getRow ($ sql, $ _POST ["auth_name"]);
    if ($ rând && password_verify ($ _POST ["auth_pass"], $ row ["pass"])) (
    $ _SESSION ["user_id"] = $ rând ["id"];
    }
    antet ("Locație: http: //". $ _SERVER ["HTTP_HOST"]. $ _SERVER ["REQUEST_URI"]);
    Ieșire;
    }

    if (isset ($ _ GET ["acțiune"]) ȘI $ _GET ["acțiune"] == "deconectare") (
    sesiune_start ();
    sesiune_distruge ();
    antet ("Locație: http: //". $ _SERVER ["HTTP_HOST"]. "/");
    Ieșire;
    }

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








    Ieșire;
    }

    Acum este suficient să scrieți linia în toate scripturile protejate
    necesită „auth.php”;
    În acest exemplu, se presupune că sesiunea a început deja și conexiunea la baza de date a fost creată folosind Class pentru lucrul sigur și convenabil cu MySQL. De asemenea, presupune că parola a fost hashing folosind funcția recomandată password_hash.
    Un exemplu de fișier protejat:

    sesiune_start ();
    includ „safemysql.class.php”;
    $ db = nou safemysql (["db" => "test"]);
    include „auth.php”;
    ?>
    secret

    deconectare

    OPS! Link-uri foarte utile:
    http://www.php.net/manual/ru/ref.session.php - cele mai recente și actualizate informații despre suportul sesiunii în PHP din documentația oficială, plus numeroase comentarii ale utilizatorilor. Lectură foarte recomandată.
    http://phpclub.ru/manrus/f/ref.session.html - Traducere FOARTE învechită a acestui capitol în limba rusă, din documentația tradusă de Alexander Pyramidin.
    http://phpclub.ru/detail/article/sessions
    Un articol cu ​​un titlu pretențios „Adevărul despre ședințe”. Lasa o impresie ambivalenta. La început, autorul vorbește FOARTE ușor despre mecanismul sesiunii, dar metodele pe care le propune spre finalul articolului sunt complet tulburi.

    Articol de manual de Dmitri Borodin de pe site
    http://php.spb.ru/ NU este recomandat.
    Băieți, e teribil de depășită. Nu numai că există inexactități faptice în el, dar sesiunile în PHP pur și simplu nu au fost folosite de mult timp.
    Mulțumesc mult lui Dima pentru ea, acesta a fost primul articol despre ședințe în limba rusă, l-am studiat chiar eu, dar acum trebuie să o trimit la o odihnă binemeritată.
    De asemenea, din păcate, multe alte articole care sunt pe Internet și nu au fost actualizate de ani de zile sunt și ele depășite.

  • Bună dragă comunitate.

    În primul rând, vreau să vă mulțumesc pentru o resursă foarte utilă. Nu o dată am găsit aici o mulțime de idei interesante și sfaturi practice.

    Scopul acestui articol este de a evidenția capcanele utilizării sesiunilor în PHP. Desigur, există documentație PHP și o mulțime de exemple, iar acest articol nu se dorește a fi un ghid complet. Este conceput pentru a dezvălui unele dintre nuanțele lucrului cu sesiuni și pentru a proteja dezvoltatorii de pierderea inutilă a timpului.

    Cel mai frecvent caz de utilizare pentru sesiuni este, desigur, autorizarea utilizatorului. Să începem cu implementarea cea mai de bază, astfel încât să o putem evolua în mod constant pe măsură ce apar noi provocări.

    (Pentru a economisi spațiu și timp, ne vom limita la exemple doar prin funcțiile de lucru cu sesiuni, în loc să construim aici o aplicație de testare cu drepturi depline, cu o ierarhie de clasă frumoasă, tratare exhaustivă a erorilor și alte lucruri corecte).

    Funcția startSession () (// Dacă sesiunea a fost deja începută, opriți execuția și returnați TRUE // (parametrul session.auto_start din fișierul de setări php.ini trebuie să fie dezactivat - valoarea implicită) if (session_id ()) return true; altfel returnează session_start (); // Notă: înainte de versiunea 5.3.0, funcția session_start () a returnat TRUE chiar și în cazul unei erori. // Dacă utilizați o versiune sub 5.3.0, faceți o validare suplimentară session_id ( ) // după apelarea funcției session_start ()) destroySession () (dacă (session_id ()) (// Dacă există o sesiune activă, ștergeți cookie-urile de sesiune, setcookie (session_name (), session_id (), time () - 60 * 60 * 24); // și distruge sesiunea session_unset ( ); session_destroy ();))

    Notă: Se presupune că cititorul are cunoștințe de bază despre sesiunile PHP, așa că nu vom acoperi cum funcționează funcțiile session_start () și session_destroy (). Sarcinile de aspect al formularului de autentificare și autentificarea utilizatorului nu au legătură cu subiectul articolului, așa că le vom omite și ele. Permiteți-mi doar să vă reamintesc că pentru a identifica utilizatorul în fiecare solicitare ulterioară, în momentul logării cu succes, trebuie să salvăm ID-ul utilizatorului într-o variabilă de sesiune (cu numele userid, de exemplu), care va fi disponibilă în toate ulterioare. cereri pe durata sesiunii. De asemenea, este necesar să implementăm procesarea rezultatului funcției noastre startSession (). Dacă funcția returnează FALSE, afișați formularul de autentificare în browser. Dacă funcția returnează TRUE, iar variabila de sesiune care conține identificatorul utilizatorului autorizat (în cazul nostru, userid-ul) există, afișați pagina utilizatorului autorizat (pentru mai multe detalii despre tratarea erorilor, consultați adăugarea din 2013-06- 07 în secțiunea privind variabilele de sesiune).

    Până acum totul este clar. Întrebările încep atunci când este necesar să se implementeze controlul inactivității utilizatorilor (sesiunea expirată), să permită mai multor utilizatori să lucreze simultan într-un singur browser și, de asemenea, să se protejeze sesiunile împotriva utilizării neautorizate. Acest lucru va fi discutat mai jos.

    Controlul inactivității utilizatorului cu instrumente PHP încorporate

    Prima întrebare care apare adesea în rândul dezvoltatorilor de tot felul de console pentru utilizatori este încheierea automată a sesiunii în caz de inactivitate din partea utilizatorului. Nu ar putea fi mai ușor decât folosirea capabilităților încorporate ale PHP. (Această opțiune nu este foarte fiabilă și flexibilă, dar să o luăm în considerare pentru a fi completă).

    Funcția startSession () (// Timeout inactivitatea utilizatorului (în secunde) $ sessionLifetime = 300; dacă (session_id ()) returnează true; // Setează durata de viață a cookie-ului ini_set ("session.cookie_lifetime", $ sessionLifetime); // Dacă Timeout inactivitatea utilizatorului este setat, setați durata de viață a sesiunii pe server // Notă: Pentru un server de producție, se recomandă să presetați acești parametri în fișierul php.ini dacă ($ sessionLifetime) ini_set ("session.gc_maxlifetime", $ sessionLifetime ); if (session_start ( )) (setcookie (session_name (), session_id (), time () + $ sessionLifetime); return true;) else return false;)

    Puține explicații. După cum știți, PHP determină ce sesiune să înceapă prin numele cookie-ului transmis de browser în antetul cererii. Browserul, la rândul său, primește acest cookie de la server, unde funcția session_start () îl plasează. Dacă cookie-ul a expirat în browser, acesta nu va fi transmis în cerere, ceea ce înseamnă că PHP nu va putea determina ce sesiune să înceapă și va considera acest lucru drept crearea unei noi sesiuni. Parametrul de setări PHP session.gc_maxlifetime, care este setat egal cu expirarea timpului de inactivitate a utilizatorului, stabilește durata de viață a sesiunii PHP și este controlat de server. Controlul duratei de viață a sesiunii funcționează după cum urmează (aici considerăm un exemplu de stocare a sesiunii în fișiere temporare ca cea mai comună și implicită versiune în PHP).

    În momentul creării unei noi sesiuni, un fișier numit sess_ este creat în directorul setat ca director pentru stocarea sesiunilor în parametrul de setări PHP session.save_path. , Unde - identificatorul de sesiune. În plus, în fiecare solicitare, în momentul începerii unei sesiuni existente, PHP actualizează ora de modificare a acestui fișier. Astfel, în fiecare solicitare ulterioară PHP, prin diferența dintre ora curentă și ora ultimei modificări a fișierului de sesiune, poate determina dacă sesiunea este activă, sau durata de viață a expirat deja. (Mecanismul de ștergere a fișierelor vechi de sesiune este discutat mai detaliat în secțiunea următoare).

    Notă: Trebuie remarcat aici că parametrul session.gc_maxlifetime afectează toate sesiunile dintr-un singur server (mai precis, în cadrul unui proces PHP principal). În practică, aceasta înseamnă că, dacă pe server rulează mai multe site-uri și fiecare dintre ele are propriul timeout de inactivitate a utilizatorilor, atunci setarea acestui parametru pe unul dintre site-uri va duce la instalarea lui și pentru alte site-uri. Același lucru este valabil și pentru găzduirea partajată. Pentru a evita această situație, sunt utilizate directoare de sesiune separate pentru fiecare site pe un singur server. Setarea căii către directorul de sesiune se face folosind parametrul session.save_path din fișierul de setări php.ini sau apelând funcția ini_set (). După aceea, sesiunile fiecărui site vor fi stocate în directoare separate, iar parametrul session.gc_maxlifetime, setat pe unul dintre site-uri, va fi valabil doar pentru sesiunea acestuia. Nu vom lua în considerare acest caz în detaliu, mai ales că avem în stoc o opțiune mai flexibilă pentru controlul inactivității utilizatorului.

    Controlul inactivitatii utilizatorului folosind variabile de sesiune

    S-ar părea că opțiunea anterioară, cu toată simplitatea ei (doar câteva rânduri suplimentare de cod), oferă tot ce avem nevoie. Dar dacă nu orice solicitare poate fi considerată ca rezultat al activității utilizatorului? De exemplu, pagina are un cronometru care face periodic o solicitare AJAX pentru a primi actualizări de la server. O astfel de solicitare nu poate fi considerată activitate de utilizator, ceea ce înseamnă că prelungirea automată a duratei de viață a sesiunii nu este corectă în acest caz. Dar știm că PHP actualizează automat ora de modificare a fișierului de sesiune cu fiecare apel la funcția session_start (), ceea ce înseamnă că orice solicitare va duce la o prelungire a duratei de viață a sesiunii, iar timeout-ul de inactivitate al utilizatorului nu va avea loc niciodată. În plus, ultima notă din secțiunea anterioară despre complexitățile parametrului session.gc_maxlifetime poate părea prea confuză și complicată de implementat.

    Pentru a rezolva această problemă, vom abandona utilizarea mecanismelor PHP încorporate și vom introduce câteva variabile noi de sesiune care ne vor permite să controlăm singuri timpul de inactivitate a utilizatorului.

    Funcția startSession ($ isUserActivity = true) ($ sessionLifetime = 300; if (session_id ()) return true; // Setați durata de viață a cookie-ului până când browserul este închis (vom controla totul pe partea serverului) ini_set ("session.cookie_lifetime ", 0); dacă (! session_start ()) returnează fals; $ t = timp (); if ($ sessionLifetime) (// Dacă este setat timpul de expirare a inactivității utilizatorului, // verificați timpul scurs de la ultima activitate a utilizatorului / / (ora ultimei solicitări când a fost actualizată variabila de sesiune lastactivity) if (isset ($ _ SESSION ["lastactivity")) && $ t - $ _ SESSION ["lastactivity"]> = $ sessionLifetime) (// Dacă timpul scurs de la ultima activitate a utilizatorului // mai mult timeout de inactivitate, atunci sesiunea a expirat și trebuie să încheiați sesiunea destroySession (); return false;) else (// Dacă timeout-ul nu a avut loc încă, // și dacă cererea a venit ca urmare a activității utilizatorului, // actualizați variabila lastactivity cu valoarea vr-ului curent emeny, // extinzând astfel durata sesiunii cu o altă sesiuneLifetime secunde dacă ($ isUserActivity) $ _SESSION ["lastactivity"] = $ t; )) returnează adevărat; )

    Să rezumam. În fiecare cerere, verificăm dacă timeout-ul a fost atins de la ultima activitate a utilizatorului până în momentul curent, iar dacă acesta a fost atins, distrugem sesiunea și întrerupem execuția funcției, returnând FALSE. Dacă expirarea nu a fost atinsă și parametrul $ isUserActivity cu valoarea TRUE este transmis funcției, actualizăm ora ultimei activități a utilizatorului. Tot ce trebuie să facem este să stabilim în scriptul de apelare dacă cererea este rezultatul activității utilizatorului, iar dacă nu, să apelăm funcția startSession cu valoarea parametrului $ isUserActivity egală cu FALSE.

    Actualizare din 2013-06-07
    Procesarea rezultatului funcției sessionStart ().

    În comentarii, am observat că returnarea FALSE nu oferă o înțelegere completă a cauzei erorii, iar acest lucru este absolut adevărat. Nu am publicat aici tratarea detaliată a erorilor (volumul articolului oricum nu este mic), deoarece aceasta nu are legătură directă cu subiectul articolului. Dar, având în vedere comentariile, o să clarific.

    După cum puteți vedea, funcția sessionStart poate returna FALSE în două cazuri. Fie sesiunea nu a putut fi pornită din cauza unor erori interne ale serverului (de exemplu, setări incorecte ale sesiunii în php.ini), fie sesiunea a expirat. În primul caz, trebuie să redirecționăm utilizatorul către o pagină cu eroare că există probleme pe server și o formă de contact a asistenței. În al doilea caz, trebuie să transferăm utilizatorul în formularul de autentificare și să afișăm un mesaj corespunzător în acesta că sesiunea a expirat. Pentru a face acest lucru, trebuie să introducem coduri de eroare și să returnăm codul corespunzător în loc de FALSE și să îl verificăm în metoda de apelare și să acționăm în consecință.

    Acum, chiar dacă sesiunea de pe server încă există, aceasta va fi distrusă prima dată când este accesată, dacă timeout-ul de inactivitate a utilizatorului a expirat. Și acest lucru se va întâmpla indiferent de durata de viață a sesiunii setată în setările globale PHP.

    Notă: Ce se întâmplă dacă browserul a fost închis și cookie-ul pentru numele sesiunii a fost distrus automat? Solicitarea către server data viitoare când browserul este deschis nu va conține cookie-uri de sesiune, iar serverul nu va putea deschide o sesiune și nu va putea verifica timpul de expirare a inactivității utilizatorului. Pentru noi, aceasta echivalează cu crearea unei noi sesiuni și nu afectează în niciun fel funcționalitatea sau securitatea. Dar apare o întrebare corectă - cine va distruge vechea sesiune, dacă am distrus-o până acum după expirarea timpului de expirare? Sau va rămâne acum în directorul sesiunii pentru totdeauna? Pentru curățarea sesiunilor vechi, PHP are un mecanism numit colectare de gunoi. Pornește în momentul următoarei solicitări către server și curăță toate sesiunile vechi pe baza datei ultimei modificări a fișierelor de sesiune. Dar mecanismul de colectare a gunoiului nu pornește la fiecare cerere către server. Frecvența (mai precis, probabilitatea) lansării este determinată de doi parametri de setări session.gc_probability și session.gc_divisor. Rezultatul împărțirii primului parametru la al doilea este probabilitatea de a porni mecanismul de colectare a gunoiului. Astfel, pentru ca mecanismul de curățare a sesiunii să pornească la fiecare solicitare către server, acești parametri trebuie setați la valori egale, de exemplu, „1”. Această abordare asigură că directorul de sesiune este curat, dar este evident prea mare pentru server. Prin urmare, pe sistemele de producție, session.gc_divisor este setat implicit la 1000, ceea ce înseamnă că motorul de colectare a gunoiului va porni cu o probabilitate de 1/1000. Dacă experimentați cu aceste setări în fișierul dvs. php.ini, veți observa că în cazul de mai sus, când browserul se închide și șterge toate modulele cookie, există încă sesiuni vechi în directorul de sesiuni pentru o perioadă. Dar asta nu ar trebui să te îngrijoreze, pentru că după cum sa menționat deja, acest lucru nu afectează în niciun fel siguranța mecanismului nostru.

    Actualizare din 2013-06-07

    Prevenirea blocării scripturilor din cauza blocării fișierului de sesiune

    În comentarii, ei au ridicat problema înghețării scripturilor care rulează simultan din cauza blocării fișierului de sesiune (ca cea mai strălucitoare opțiune - sondaj lung).

    Pentru început, observ că această problemă nu depinde direct de încărcarea serverului sau de numărul de utilizatori. Desigur, cu cât sunt mai multe solicitări, cu atât mai lent rulează scripturile. Dar aceasta este o dependență indirectă. Problema apare doar în cadrul unei sesiuni, când serverul primește mai multe solicitări în numele unui utilizator (de exemplu, una dintre ele este un sondaj lung, iar restul sunt solicitări obișnuite). Fiecare solicitare încearcă să acceseze același fișier de sesiune, iar dacă cererea anterioară nu a deblocat fișierul, următoarea se va bloca în așteptare.

    Pentru a menține blocarea fișierelor de sesiune la minimum, este recomandat să închideți sesiunea apelând funcția session_write_close () imediat după ce au fost efectuate toate acțiunile cu variabilele de sesiune. În practică, aceasta înseamnă că nu ar trebui să stocați totul în variabilele de sesiune și să vă referiți la ele pe parcursul execuției scriptului. Și dacă trebuie să stocați unele date de lucru în variabilele de sesiune, atunci citiți-le chiar la începutul sesiunii, salvați-le în variabilele locale pentru utilizare ulterioară și închideți sesiunea (adică închiderea sesiunii folosind funcția session_write_close, nu distrugerea acesteia folosind sesiune_distruge).

    În exemplul nostru, aceasta înseamnă că imediat după deschiderea unei sesiuni, verificând durata de viață a acesteia și existența unui utilizator autorizat, trebuie să citim și să salvăm toate variabilele de sesiune suplimentare necesare aplicației (dacă există), apoi să închidem sesiunea folosind session_write_close ( ) apelați și continuați execuția unui script, fie că este un sondaj lung sau o solicitare obișnuită.

    Protejarea sesiunilor împotriva utilizării neautorizate

    Să ne imaginăm o situație. Unul dintre utilizatorii tăi conectează un troian care fură cookie-ul browserului (în care este stocată sesiunea noastră) și îl trimite la adresa de e-mail specificată. Atacatorul primește un cookie și îl folosește pentru a falsifica o solicitare în numele utilizatorului nostru autorizat. Serverul acceptă și procesează cu succes această solicitare ca și cum ar proveni de la un utilizator autorizat. Dacă nu este implementată verificarea suplimentară a adresei IP, un astfel de atac va duce la o piratare cu succes a contului utilizatorului cu toate consecințele care decurg.

    De ce este posibil acest lucru? Evident, pentru că numele și identificatorul sesiunii sunt întotdeauna aceleași pe toată durata de viață a sesiunii, iar dacă primiți aceste date, puteți trimite liber solicitări în numele altui utilizator (firesc, pe durata de viață a acestei sesiuni). Poate că acesta nu este cel mai frecvent tip de atacuri, dar, teoretic, totul pare destul de fezabil, mai ales având în vedere că un astfel de troian nici măcar nu are nevoie de drepturi de administrator pentru a jefui cookie-urile browserului utilizatorului.

    Cum te poți apăra de astfel de atacuri? Din nou, evident prin limitarea duratei de viață a identificatorului de sesiune și schimbarea periodică a identificatorului într-o singură sesiune. De asemenea, putem schimba numele sesiunii, ștergându-l complet pe cel vechi și creând o nouă sesiune, copiend toate variabilele de sesiune din cea veche în ea. Dar acest lucru nu afectează esența abordării, prin urmare, pentru simplitate, ne vom restrânge doar la identificatorul de sesiune.

    Este clar că cu cât durata de viață a identificatorului de sesiune este mai scurtă, cu atât mai puțin timp va avea un atacator pentru a obține și a utiliza cookie-uri pentru a falsifica cererea unui utilizator. În mod ideal, pentru fiecare solicitare ar trebui folosit un nou identificator, minimizând astfel posibilitatea de a utiliza sesiunea altcuiva. Dar vom lua în considerare cazul general în care timpul de regenerare a ID-ului sesiunii este setat în mod arbitrar.

    (Să omitem partea din cod care a fost deja discutată).

    Funcția startSession ($ isUserActivity = true) (// Durata de viață a ID-ului sesiunii $ idLifetime = 60; ... if ($ idLifetime) (// Dacă durata de viață a ID-ului sesiunii este setată, // verificați timpul scurs de când a fost creată sesiunea sau ultima regenerare // (ora ultimei solicitări când a fost actualizată variabila sesiune starttime) if (isset ($ _ SESSION ["starttime"))) (dacă ($ t - $ _ SESSION ["starttime"]> = $ idLifetime) (// Time session ID expired // Generați un nou ID session_regenerate_id (true); $ _SESSION ["starttime"] = $ t;)) altfel (// Ajungem aici dacă sesiunea tocmai a fost creată // Setați ora de generare a ID-ului sesiunii la ora curentă $ _SESSION [„starttime”] = $ t;)) returnează adevărat;)

    Deci, la crearea unei noi sesiuni (care apare atunci când utilizatorul se conectează cu succes), setăm variabila sesiune starttime, care stochează pentru noi ora ultimei generații a identificatorului de sesiune, la o valoare egală cu ora actuală a serverului. Mai departe, în fiecare cerere, verificăm dacă a trecut suficient timp (idLifetime) de la ultima generație a identificatorului, iar dacă a trecut, generăm unul nou. Astfel, dacă în perioada de viață specificată a identificatorului, atacatorul care a primit cookie-ul utilizatorului autorizat nu reușește să-l folosească, cererea falsă va fi considerată de către server ca neautorizată, iar atacatorul va fi dus la pagina de autentificare.

    Notă: Noul identificator de sesiune intră în cookie-ul browser atunci când este apelată funcția session_regenerate_id (), care trimite un cookie nou, similar cu funcția session_start (), deci nu trebuie să actualizăm cookie-urile noi înșine.

    Dacă vrem să ne securizăm cât mai mult posibil sesiunile, este suficient să setăm durata de viață a identificatorului la una, sau chiar să punem funcția session_regenerate_id () în afara parantezei și să eliminăm toate verificările, ceea ce va duce la regenerarea identificatorului în fiecare cerere. (Nu am testat impactul acestei abordări asupra performanței și pot spune doar că funcția session_regenerate_id (adevărat) efectuează în esență doar 4 acțiuni: generarea unui nou identificator, crearea unui antet din cookie-ul de sesiune, ștergerea celui vechi și crearea unui nou fișier de sesiune).

    Digresiune lirică: Dacă troianul se dovedește a fi atât de inteligent încât nu va trimite cookie-uri atacatorului, ci organizează el însuși trimiterea unei cereri false pregătite în prealabil imediat după primirea cookie-ului, metoda descrisă mai sus nu va putea proteja cel mai probabil împotriva unui astfel de atac, deoarece între momentul în care troianul primește cookie-ul și trimiterea celui fals practic nu va fi nicio diferență în cerere și există o mare probabilitate ca ID-ul sesiunii să nu fie regenerat în acest moment.

    Abilitatea de a lucra simultan într-un singur browser în numele mai multor utilizatori

    Ultima sarcină pe care aș dori să o iau în considerare este posibilitatea de a lucra simultan într-un singur browser pentru mai mulți utilizatori. Această caracteristică este utilă în special în etapa de testare, atunci când trebuie să emulați munca simultană a utilizatorului și este recomandabil să faceți acest lucru în browserul dvs. preferat și să nu utilizați întregul arsenal disponibil sau să deschideți mai multe instanțe ale browserului în modul „incognito”. .

    În exemplele noastre anterioare, nu am setat în mod explicit numele sesiunii, așa că a fost folosit numele PHP implicit (PHPSESSID). Aceasta înseamnă că toate sesiunile pe care le-am creat până acum au trimis cookie-uri către browser sub numele PHPSESSID. Evident, dacă numele cookie-ului este întotdeauna același, atunci nu există nicio modalitate în cadrul aceluiași browser de a organiza două sesiuni cu același nume. Dar dacă am folosi un nume de sesiune diferit pentru fiecare utilizator, atunci problema ar fi rezolvată. Așa că o vom face.

    Funcția startSession ($ isUserActivity = true, $ prefix = null) (... dacă (session_id ()) returnează adevărat; // Dacă prefixul utilizatorului este trecut în parametri, // setați un nume unic de sesiune care include acest prefix, // altfel setați un nume comun tuturor utilizatorilor (de exemplu, MYPROJECT) session_name ("MYPROJECT". ($ prefix? "_". $ prefix: "")); ini_set ("session.cookie_lifetime", 0) ; dacă (! session_start ()) returnează false; ...)

    Acum tot ce rămâne este să vă asigurați că scriptul de apelare transmite un prefix unic pentru fiecare utilizator la funcția startSession (). Acest lucru se poate face, de exemplu, prin trecerea unui prefix în parametrii GET / POST ai fiecărei solicitări, sau printr-un cookie suplimentar.

    Concluzie

    În concluzie, voi oferi codul final complet al funcțiilor noastre pentru lucrul cu sesiuni PHP, inclusiv toate sarcinile discutate mai sus.

    Funcția startSession ($ isUserActivity = true, $ prefix = null) ($ sessionLifetime = 300; $ idLifetime = 60; dacă (session_id ()) returnează adevărat; session_name ("MYPROJECT". ($ Prefix? "_". $ Prefix: "")); ini_set ("session.cookie_lifetime", 0); if (! session_start ()) return false; $ t = time (); if ($ sessionLifetime) (dacă (isset ($ _ SESSION ["lastactivity") ] ) && $ t - $ _ SESSION ["lastactivity"]> = $ sessionLifetime) (destroySession (); return false;) else (dacă ($ isUserActivity) $ _SESSION ["lastactivity"] = $ t;)) dacă ( $ idLifetime ) (dacă (isset ($ _ SESSION ["starttime"))) (dacă ($ t - $ _ SESSION ["starttime"]> = $ idLifetime) (session_regenerate_id (adevărat); $ _SESSION ["starttime"] = $ t; )) else ($ _SESSION ["starttime"] = $ t;)) returnează adevărat;) funcția destroySession () (dacă (session_id ()) (session_unset (); setcookie (session_name (), session_id () , timp () -60 * 60 * 24); session_destroy ();))

    Sper că acest articol va economisi ceva timp pentru cei care nu au intrat niciodată cu adevărat în mecanismul sesiunilor și va oferi suficientă înțelegere a acestui mecanism pentru cei care abia încep să se familiarizeze cu PHP.

    Sesiuni în PHP sau modul în care datele despre un utilizator sau client care a intrat pe site sunt salvate la navigarea între paginile site-ului fără mare dificultate. Lecția este foarte importantă. Relevant pentru crearea a 95% din site-uri.

    Ce este sesiune în php

    Sesiunile sunt folosite pentru a stoca informații despre date temporare (de exemplu, că utilizatorul a intrat pe site) atunci când navighează între paginile aceluiași site. Când utilizați sesiuni, datele sunt salvate în fișiere temporare pe server.
    Cel mai adesea, sesiunile (și cookie-urile, apropo, de asemenea) sunt folosite atunci când se creează magazine online, forumuri, forumuri, rețele sociale, bloguri și alte resurse. Comoditatea sistemului de sesiune constă în stocarea informațiilor temporare ale utilizatorului/clientului conectat, ale căror date se află în acces rapid pentru un anumit timp. Sesiunea are o dată naturală de expirare - până când browserul este închis. Dacă închideți doar pagina, atunci când deschideți site-ul, datele despre utilizator/cumpărător vor fi în continuare disponibile.

    Logica sesiunii

    Sesiunea (sau sesiune) este un fel de stocare temporară a datelor. Vă avertizez imediat că merită să salvați o cantitate mică de date. De exemplu, autentificarea și parola utilizatorului de autentificare sau numărul de serie al acestuia în baza de date.

    Exemplu de lucru
    1. Utilizatorul introduce un nume de utilizator și o parolă și intră pe site
    2. Datele cu login și parola sunt salvate în sesiunea uneia dintre paginile site-ului:

    Fişier index.php

    Session_start (); // fiecare fișier în care doriți să utilizați datele de sesiune trebuie să conțină comanda „start session” la începutul codului

    $ login = "admin";
    $ parola = "trece";
    $ _SESSION ["login"] = $ autentificare; // salvează variabila care conține autentificarea
    $ _SESSION ["parolă"] = $ parola; // salvează variabila care conține parola

    3. Când accesați o altă pagină a site-ului, aceste date vor fi și ele disponibile:

    Fişier exemplu.php(sau orice alta pagina)

    Echo „Autentificarea dvs.”. $ _ SESSION [„autentificare”]; // va afișa „Autentificarea dvs. este admin”, deși nu am înregistrat date pe această pagină!
    Vezi, e simplu!

    4. Dacă doriți să ștergeți datele sesiunii, atunci este suficient:

    Fişier exemplu.php

    Session_start (); // „începe sesiunea” din nou

    Dezactivat ($ _ SESSION [„login”]); // așa a fost neînregistrată sau „distrusă” variabila
    echo "Autentificarea dvs.". $ _ SESSION ["conectare"]; // va afișa „Autentificarea dvs.”. Din moment ce l-am distrus în ultima linie, nici nu există date.

    Session_destroy (); // distrug sesiunea. Toate datele, inclusiv $ _SESSION [„parola”], au dispărut. La cerere, va fi afișată o eroare
    În general, un astfel de transfer este similar cu metoda POST, dar nu mai trebuie să scrieți mult cod inutil și toate datele transferate de la o pagină la alta sunt stocate în fișiere temporare pe server. Din nou, sesiunile ar trebui să conțină cantități mici de date, astfel încât acestea sunt potrivite pentru stocarea numelui de utilizator/parolă, a coșului de cumpărături și a altor volume mici.

    Transmiterea unei valori sau a unei matrice folosind o sesiune PHP

    Într-o sesiune, puteți scrie nu numai un șir, ci și o matrice de date. Doar nu exagerați cu dimensiunea matricei, deoarece toate acestea vor afecta performanța și spațiul ocupat pe server.

    Folosim din nou o anumită pagină de pornire index.php

    Session_start ();

    $ r = matrice („unu”, „două”, „trei”);

    $ _SESIUNE ["arr"] = $ r;

    La pagina unde este afișat totul
    Am salvat datele în sesiune și urmăm linkul către o altă pagină, unde vom afișa toate datele.

    Destinatar fișier, pagină test.php unde deschidem matricea

    Session_start ();
    print_r ($ _ SESIUNE ["arr"]);
    // va ieși
    /*
    Matrice
    => unul
    => doi
    => trei
    */
    ?>
    S-ar putea să doriți să actualizați un tutorial. În general, totul ar trebui să fie clar.

    Alte funcții pentru lucrul cu sesiuni

    session_unregister (șir)- sesiunea uită valoarea variabilei globale specificate;
    session_destroy ()- sesiunea este distrusă (de exemplu, dacă utilizatorul a părăsit sistemul prin apăsarea butonului de deconectare);
    session_set_cookie_params (int lifetime [, calea șirului [, domeniul șirului]])- folosind această funcție, puteți seta cât va dura sesiunea prin setarea unix_timestamp, care determină ora decesului sesiunii.

    Lista de funcții pentru lucrul cu sesiuni (sesiune) în php
    session_cache_expire - Returnează expirarea memoriei cache curente
    session_cache_limiter - Obțineți și/sau setați limita actuală a memoriei cache
    session_commit - un alias pentru session_write_close ()
    session_decode - Decodifică datele sesiunii din șir
    session_destroy - Distruge toate datele înregistrate pentru sesiune
    session_encode - criptează datele sesiunii curente ca șir
    session_get_cookie_params - Obține parametrii cookie-urilor de sesiune
    session_id - obține și/sau setează ID-ul sesiunii curente
    session_is_registered - determină dacă o variabilă este înregistrată în sesiune
    session_module_name - Obțineți și/sau instalați modulul pentru sesiunea curentă
    session_name - obține și/sau setează numele sesiunii curente
    session_regenerate_id - Modifică id-ul sesiunii curente cu cel nou generat
    session_register - înregistrează una sau mai multe variabile pentru sesiunea curentă
    session_save_path - obține și/sau setează calea pentru salvarea sesiunii curente
    session_set_cookie_params - setează parametrii cookie-urilor de sesiune
    session_set_save_handler - setează funcțiile de stocare a sesiunii la nivel de utilizator
    session_start - inițializează datele sesiunii
    session_unregister - Anulează înregistrarea unei variabile din sesiunea curentă
    session_unset - Eliberează toate variabilele de sesiune
    session_write_close - Scrie datele sesiunii și sfârșitul sesiunii

    Exemple de sesiune

    Contorul de vizualizări de pagină în timpul sesiunii. Un exemplu ilustrativ de muncă. Cu toate acestea, după închiderea browserului, numărătoarea inversă va începe din nou.

    Contor de vizite la o pagină în cadrul unei sesiuni

    // Un exemplu simplu de utilizare a sesiunilor fără cookie-uri.
    nume_sesiune („test”);
    sesiune_start ();
    $ _SESSION ["count"] = @ $ _SESSION ["count"] + 1;
    ?>

    Tejghea


    În sesiunea curentă de lucru cu browserul, ați deschis această pagină
    timp (e).
    Închideți browserul pentru a reseta acest contor.
    Click aici pentru a reîmprospăta pagina!
    Cu fiecare tranziție, contorul va crește cu 1)

    Vă mulțumim pentru atenție! Mult succes in demersurile tale!

    Înainte de a defini termenul „sesiune”, să aruncăm o privire la fundal, de ce era nevoie de sesiuni, luați în considerare o caracteristică a protocolului HTTP.

    Una dintre principalele caracteristici ale protocolului HTTP este că nu obligă serverul să stocheze informații despre client între cereri, adică să identifice clientul. Acesta este așa-numitul protocol apatrid. Comunicarea dintre client și server se încheie imediat ce procesarea cererii curente este finalizată. Se presupune că fiecare nouă cerere către server este complet unică și independentă, chiar dacă a fost retrimisă din aceeași sursă.

    Ce se întâmplă dacă lăsăm natura apatridă a protocolului HTTP și nu autentificăm utilizatorul? Stările de sesiune pot fi ușor eliminate dacă site-ul dvs. conține informații statice (anonimizate), cum ar fi un articol de știri format din text și imagini. Într-un astfel de context, este complet inutilă asocierea mai multor solicitări cu același utilizator. La urma urmei, conținutul articolului nu se va schimba în niciun fel, fie că este vorba de zece solicitări de pe un dispozitiv sau zece solicitări de la diferite persoane de pe diferite dispozitive.

    Dar, de îndată ce vom transfera informații personale pe server, trebuie să ne asigurăm cumva că serverul ne asociază toate solicitările noastre, iar pe viitor identifică corect toate cererile trimise de la noi. Dacă acest lucru nu se face, atunci cu fiecare nouă solicitare vom fi obligați să retransmitem datele personale necesare. De exemplu, o autentificare pentru a vă introduce contul personal pe site, sau informații precum numele, adresa de livrare, atunci când faceți o achiziție într-un magazin online.

    În astfel de situații, când este necesară personalizarea solicitărilor de la un client, vom folosi sesiuni.

    Sesiune (sesiune) este o anumită perioadă de timp în care o aplicație web poate determina toate solicitările de la un client.

    Când un client transmite pentru prima dată date personale într-o solicitare, o nouă sesiune este creată pe server pentru acel client. Pe durata sesiunii, toate cererile de la acest client vor fi recunoscute în mod unic și asociate cu acesta. După acest timp, comunicarea cu clientul se va pierde, iar următoarea cerere de la acesta va fi procesată ca absolut unică, în nici un fel legată de cele anterioare.

    De exemplu, la efectuarea unei achiziții într-un magazin online, informațiile personale ale utilizatorului sunt salvate în sesiune în timp ce acesta navighează pe site. Acestea sunt articolele selectate din coș, adresa de livrare, informațiile de contact și așa mai departe.

    Acum să vedem cum putem implementa acest lucru din punct de vedere tehnic. În general, există mai multe tehnici de gestionare a sesiunilor client, numărul și metoda de implementare a acestora depind în mare măsură de platforma web sau de tehnologia care rulează pe server. În acest tutorial, vom acoperi următoarele:

    1. câmpuri de formular ascunse
    2. cookie-uri
    3. sesiune (sesiune, stare sesiune)

    Să încercăm să le implementăm folosind platforma ASP.NET. Să aruncăm o privire rapidă asupra primelor două mecanisme și să acordăm o atenție deosebită celui de-al treilea, ca fiind mai fiabil, mai convenabil și mai sigur.

    Câmpuri de formular ascunse

    Esența acestei abordări este că oferim navigare pe site folosind formulare html standard. Și cu fiecare cerere următoare, salvăm datele din cea anterioară în câmpuri ascunse din formular. De exemplu:

    @using (Html.BeginForm ("Formulare2", "Acasă", FormMethod.Post)) (

    Comandând un fel de mâncare

    }
    Public ActionResult Forms2 () (ViewBag.UserName = Request.Form [„userName”]; returnează Vizualizare ();)
    @using (Html.BeginForm ("Forms3", "Home", FormMethod.Post)) (

    @ ($ "Bună ziua (ViewBag.UserName)! Ce vei comanda?")

    }

    În acest exemplu, obținem numele de utilizator pe primul formular html. Mai departe în controler în metodă Formulare2 () preluăm această valoare din colecție Formăși trece-l la vedere prin obiect ViewBag... Această vizualizare generează codul pentru noul formular și stochează numele utilizatorului într-un câmp ascuns. Astfel, valoarea numelui de utilizator va fi transferată în a treia formă împreună cu informații suplimentare - valoarea câmpului cu numele "nume alimente"... etc.

    Să aruncăm o privire la caracteristicile acestei abordări. Practic nu există avantaje, cu excepția faptului că această tehnică poate fi implementată foarte rapid. Dar din nou, și alte abordări pot fi implementate foarte rapid. Dar există dezavantaje și destul de semnificative:


    Cookie-uri

    Cookies public ActionResult2 () (cookie HttpCookie = nou HttpCookie („nume utilizator”, HttpUtility.UrlEncode (Formular Solicitare [„Nume utilizator”)); cookie.Expires = DateTime.UtcNow.AddHours (1); Response.Cookies.Add ( cookie); returnează Vizualizare ();)
    @using (Html.BeginForm ("Cookies3", "Acasă", FormMethod.Post)) (

    @ ($ "Bună ziua (HttpUtility.UrlDecode (Solicitare.Cookies [" userName "] ?. Value))! Ce vei comanda?")

    }

    În această abordare, nu stocăm datele sesiunii direct pe formular, în schimb, folosim mecanismul cookie standard între client și server. Toate datele utilizatorului sunt stocate în cookie-uri.

    Atunci când alegem această abordare, din nou, principala problemă rămâne securitatea datelor noastre, pe care le transferăm pe server - este ușor să le înlocuim sau să le furăm, este clar. De asemenea, dacă acceptarea cookie-urilor de pe site-uri este dezactivată în setările de confidențialitate ale browserului clientului, atunci această opțiune pentru menținerea unei sesiuni nu va funcționa deloc.

    Astfel, este foarte descurajat să transferați date importante și secrete în primele două moduri, cum ar fi autentificarea, parolele, numerele de card și de cont, datele pașapoartelor, locul de reședință etc.

    Mecanism de gestionare a sesiunii pe partea de server (Session, SessionState)

    Să aruncăm o privire la modul în care mecanismul de sesiune funcționează din partea serverului și din partea clientului.

    Cu setările standard ale operațiunii de stare a sesiunii, așa-numitele. cookie de sesiune Algoritmul este următorul:

    1. Pentru absolut fiecare cerere nouă către server (nu contează dacă sunt clienți diferiți sau unul) ASP.NET generează un identificator de sesiune unic.
      Identificatorul de sesiune este un număr generat aleatoriu, codificat folosind un algoritm special într-un șir de 24 de caractere. Șirul este format din litere minuscule de la A la Z, precum și din numere de la 0 la 5. Un exemplu de identificator este hjnyuijl1pam3vox2h5i41in
    2. Dacă, în timpul solicitării curente, datele clientului NU sunt salvate pentru a lucra în continuare cu acesta, atunci durata de viață a sesiunii acestui client se termină (nu începe efectiv). În acest caz, identificatorul de sesiune generat anterior devine invalid (din moment ce nu a fost folosit). Ca răspuns la o astfel de solicitare, clientul nu primește nimic care să o asocieze cu o nouă sesiune.
    3. Dacă datele clientului (de exemplu, numele, adresa de expediere) sunt stocate pe server, ASP.NET asociază datele stocate cu un ID de sesiune generat anterior. În continuare, este creat un cookie special de sesiune și acest identificator este de asemenea scris în el. Acest cookie este adăugat ca răspuns la o solicitare și stocat în browserul clientului. Astfel, se creează o conexiune între client și informațiile sale personalizate de pe server. O nouă sesiune a fost creată pentru acest client.
    4. Cu fiecare cerere următoare, clientul trimite un identificator personal de sesiune către server prin cookie-uri. Serverul se potrivește cu identificatorii și „recunoaște” clientul în cadrul sesiunii curente.
    5. Atâta timp cât clientul transmite cheia personală, sesiunea este considerată activă. Sesiunea se poate încheia din diverse motive, de exemplu, manual pe partea serverului sau după un anumit timp stabilit (timeout).

    Să trecem de la teorie la practică. Să programăm acest algoritm și să vedem cum funcționează. Pentru aceasta folosim o clasă specială HttpSessionState. Când lucrați într-un controler, puteți utiliza proprietatea HttpContext.Session. Lucrul cu o sesiune este foarte simplu, ca și cu orice NameValueCollection:

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

    În această bucată de cod, scriem numele de utilizator în starea sesiunii. Luăm acest nume din formularul html pe care ni l-a trimis. În plus, prin proprietăți, aflăm dacă această sesiune tocmai a fost creată, adică în cadrul solicitării curente (dacă da, atunci valoarea proprietății IsNewSession va fi adevărată) și identificatorul unic al sesiunii . După procesarea cererii, acest identificator va fi înregistrat automat în cookie-ul de sesiune (dacă nu este deja) și trimis în răspuns clientului.

    În browser-ul clientului, puteți observa cookie-ul corespunzător și identificatorul sesiunii sale:

    La următoarea solicitare din partea acestui client, să citim numele său salvat anterior din sesiune. De asemenea, vom forța sfârșitul sesiunii. Lucrarea cu acest client este terminată, de exemplu, toate datele au fost procesate și bunurile au fost trimise.

    String userName = Sesiune [„userName”]. ToString (); // procesarea cererii ... Session.Abandon ();

    După cum puteți vedea, lucrul cu sesiuni este foarte simplu și convenabil. Majoritatea proceselor asociate procesării unei sesiuni au loc automat în fundal. Desigur, dezvoltatorul poate interveni în orice etapă a procesării sesiunii și poate face propriile ajustări.

    Să aruncăm o privire la cele mai interesante proprietăți și metode ale clasei HttpSessionState care sunt cel mai des folosite în muncă:

    Articol- returnează un element de date după indexul său
    Articol- returnează un articol prin cheia sa
    Eliminați (index)- elimină un element de date după indexul său
    Eliminați (cheie)- șterge un articol cu ​​cheia sa
    Clar ()- șterge toate datele
    Numara- returnează numărul total de elemente de date pentru sesiunea curentă
    Abandonează ()- încheie forțat ședința
    Sesiune ID- returnează identificatorul sesiunii curente
    IsNewSession- returnează true dacă sesiunea a fost creată în cadrul solicitării curente
    Pauză- returnează numărul de minute permise între solicitări înainte de încheierea sesiunii din cauza unui timeout (în mod implicit, 20 de minute)

    Puteți modifica setările pentru o sesiune fie programatic în cod prin membrii clasei HttpSessionState, fie prin configurația aplicației (). De exemplu:

    În configurația de mai sus, am indicat că expirarea sesiunii va fi de 40 de minute, datele de sesiune ale utilizatorului vor fi stocate în RAM, vor fi folosite cookie-uri de sesiune și, de asemenea, am schimbat numele standard al unui astfel de cookie cu al nostru.

    Și încă o notă importantă în ceea ce privește securitatea. Când încheiați sesiunea utilizatorului cu metoda Session.Abandon (); cookie-ul de sesiune care stochează identificatorul de sesiune SessionId nu este șters în browserul utilizatorului. Aceasta înseamnă că, dacă utilizatorul începe o nouă sesiune în viitorul apropiat fără a închide browserul, atunci același SessionId va fi atribuit noii sale sesiuni. Este recomandabil să atribuiți întotdeauna un nou identificator unic fiecărei sesiuni noi, pentru aceasta trebuie să ștergem manual cookie-ul de sesiune după ce sesiunea este închisă:

    Sesiune.Clear (); // șterge sesiunea Session.Abandon (); // anulați sesiunea // ștergeți manual modulele cookie ca acest Response.Cookies.Add (noul HttpCookie ("ASP.NET_SessionId", "")); // sau scurtează durata de viață a răspunsului.Cookies [„ASP.NET_SessionId”]. Expiră = DateTime.Now.AddYears (-30); //ASP.NET_SessionId este numele implicit pentru cookie-ul de sesiune, îl puteți avea pe al dvs

    Așa se urmărește starea sesiunii de utilizator pe platforma ASP.NET, folosind sesiuni. Această abordare este standard și recomandată pentru utilizare atunci când este necesară stocarea informațiilor despre utilizator și identificarea acestuia între cererile către server.

    Utilizând o sesiune PHP, serverul vă identifică și vă permite să efectuați operațiunile necesare: modificarea informațiilor de pe diverse pagini web, adăugarea de informații noi etc. După ce ați terminat lucrul pe site, ștergeți sesiunea curentă făcând clic pe butonul „Deconectare”:

    Ce este o sesiune PHP?

    O sesiune PHP este o modalitate de a stoca informații în variabile de sesiune care pot fi folosite pentru a se autentifica în mai multe pagini web. Spre deosebire de cookie-uri, informațiile despre sesiune nu sunt stocate pe computerul utilizatorului. În schimb, sesiunea creează un fișier pe server într-un director temporar.

    Aceste informații, stocate pe parcursul sesiunii, sunt disponibile pentru toate paginile web ale resursei. Pe server, locația fișierului temporar este determinată de parametrul session.save_path din fișierul de configurare php.ini.

    Când creați o sesiune PHP, se fac următoarele trei lucruri:

    • Când se creează o sesiune, PHP generează un identificator unic, care este un șir aleator de 32 de numere hexazecimale. Identificatorul de viață al sesiunii PHP arată cam așa: 9c8foj87c3jj973actop1re472e8774;
    • Serverul trimite un cookie numit PHPSESSID către computerul utilizatorului pentru a stoca un șir unic de identificare a sesiunii;
    • Serverul generează un fișier în directorul temporar specificat care conține numele identificatorului unic de sesiune cu un prefix sess _g. sess_9c8foj87c3jj973actop1re472e8774.

    Aceste setări ajută scriptul PHP să extragă valorile variabilelor de sesiune din fișier. Pe partea de client, PHPSESSID conține identificatorul de sesiune. Acesta confirmă numele fișierului de căutat într-un anumit director din partea serverului, din care variabilele de sesiune pot fi preluate și utilizate pentru validare.

    Utilizatorul poate încheia sesiunea făcând clic pe butonul de deconectare, care apelează funcția session_destroy (). Când utilizatorul închide browserul, sesiunea PHP se închide automat. În caz contrar, serverul va încheia sesiunea după perioada de timp specificată.

    Sintaxa sesiunii în PHP

    În timpul autorizării sesiunii PHP, acesta este creat folosind funcția session_start () și șters folosind funcția session_destroy (). Variabila globală PHP, cunoscută sub numele de $ _SESSION, este utilizată pentru a seta valorile variabilelor de sesiune. Puteți reseta toate valorile setate pentru variabilele de sesiune folosind funcția session_unset ().

    Operații de sesiune

    Vom analiza următoarele operații folosind o sesiune PHP, precum și exemple.

    • Pornirea unei sesiuni PHP și setarea variabilelor acesteia: o nouă sesiune PHP este pornită folosind funcția session_start (). După ce sesiunea a fost creată, puteți seta valorile variabilelor sale de sesiune folosind $ _SESSION. Am stabilit valori pentru variabilele „ ID-ul de utilizator” — “php_user" și " parola” — “tutoriale”:

    Sesiuni PHP - creare Sesiunea PHP a început și variabilele de sesiune sunt setate! ";?>

    Rezultat: ca urmare a rulării codului PHP de mai sus pe server, va fi afișat următorul mesaj:


    • Obținerea valorilor variabilelor de sesiune PHP: Puteți obține valorile variabilelor pe care le-am setat în timpul ultimei sesiuni de conectare PHP. Când deschidem o sesiune PHP la începutul fiecărei pagini ( session_start ()), trebuie indicat codul de mai jos. Preluăm și afișăm aceste valori folosind variabila globală $ _SESSION:

    Sesiune PHP - obținerea valorilor
    "; echo" Parola este ". $ _SESSION [" parola "].". ";?>

    Rezultat: Când rulăm codul PHP de mai sus pe server, primim următorul mesaj ca rezultat. Sunt afișate valorile variabilelor de sesiune pe care le-am setat mai devreme după crearea sesiunii PHP.


    • Actualizarea valorilor variabilelor de sesiune PHP: În timpul unei sesiuni, puteți actualiza valorile variabilelor acesteia. Mai întâi, trebuie să deschidem o sesiune PHP la începutul fiecărei pagini ( session_start ()). În codul de mai jos, actualizăm valorile variabilelor „ ID-ul de utilizator” — “utilizator_php_nou" și " parola” — “educaţie”.

    Puteți imprima o serie de variabile de sesiune și valorile acestora folosind funcția print_r ($ _SESSION), după cum se arată mai jos:

    Sesiune PHP - modificarea valorilor
    "; print_r ($ _ SESIUNE);?>

    Rezultat: când rulăm codul PHP de mai sus pe server, primim următorul mesaj. Acesta va conține o serie de variabile de sesiune cu noile lor valori:


    • Ștergerea unei sesiuni PHP și resetarea tuturor valorilor variabilelor de sesiune: Puteți reseta o sesiune PHP utilizând funcția session_unset () și ștergeți sesiunea curentă folosind funcția session_destroy ():

    Sesiune PHP - șterge
    Sesiunea PHP și toate variabilele de sesiune au fost șterse cu succes!

    "; ?>

    Rezultat: Când rulăm codul PHP de mai sus pe serverul web, va afișa următorul mesaj:


    Concluzie

    În acest articol, am vorbit despre diverse funcții pentru lucrul cu sesiuni PHP, sintaxa acestora. Spre deosebire de cookie-uri, informațiile despre sesiune sunt stocate pe partea serverului. Acest lucru face sesiunile PHP mai fiabile.

    Top articole similare