În acest ultim capitol vom examina aspectele de securitate ale HTTP, inclusiv modul de identificare a utilizatorilor, cum funcționează autentificarea HTTP și de ce unele scenarii necesită HTTPS (HTTP securizat). Pe parcurs, vom învăța, de asemenea, un pic despre cum să gestionăm statul cu HTTP.
HTTP este un protocol fără stat, ceea ce înseamnă că fiecare tranzacție de solicitare-răspuns este independentă de orice tranzacție anterioară sau viitoare. Nu există nimic în protocolul HTTP care să impună unui server să păstreze informații despre o solicitare HTTP. Tot ce trebuie să faceți serverul este să generați un răspuns pentru fiecare solicitare. Fiecare solicitare va purta toate informațiile pe care un server trebuie să le creeze.
Natura apatridă a HTTP este unul din factorii determinanți ai succesului web-ului. Serviciile stratificate pe care le-am analizat în capitolul anterior, servicii cum ar fi cache-ul, sunt toate posibile (sau cel puțin ușor), deoarece fiecare mesaj conține toate informațiile necesare procesării mesajului. Proxy serverele și serverele web pot inspecta, transforma și cache mesaje. Fără caching-ul, web-ul nu putea să scadă pentru a răspunde cerințelor internetului.
Cu toate acestea, majoritatea aplicațiilor web și a serviciilor pe care le construim pe HTTP sunt extrem de clare.
O aplicație bancară va dori ca un utilizator să se conecteze înainte de a permite utilizatorului să-și vizualizeze resursele legate de cont. Pe măsură ce fiecare cerere de apatridie ajunge pentru o resursă privată, aplicația dorește să se asigure că utilizatorul a fost deja autentificat. Un alt exemplu este când utilizatorul dorește să deschidă un cont și să completeze formularele într-un expert de trei pagini. Aplicația va dori să se asigure că prima pagină a expertului este completă înainte de a permite utilizatorului să trimită a doua pagină.
Din fericire, există multe opțiuni pentru stocarea stării într-o aplicație web. O abordare este aceea de a încorpora statul în resursele care sunt transferate clientului, astfel încât toată starea cerută de aplicație să revină la următoarea solicitare. Această abordare necesită în mod obișnuit câteva câmpuri de intrare ascunse și funcționează cel mai bine pentru starea de scurtă durată (cum ar fi starea necesară pentru a trece printr-un expert în trei pagini). Starea de încorporare în resursă păstrează întreaga stare în interiorul mesajelor HTTP, deci este o abordare extrem de scalabilă, dar poate complica programarea aplicațiilor.
O altă opțiune este de a stoca starea pe server (sau în spatele serverului). Această opțiune este necesară pentru o stare care trebuie să fie îndelungată. Să presupunem că utilizatorul trimite un formular pentru a-și schimba adresa de e-mail. Adresa de e-mail trebuie să fie întotdeauna asociată cu utilizatorul, astfel încât aplicația să poată lua noua adresă, să confirme adresa și să stocheze adresa într-o bază de date, un fișier sau să apeleze un serviciu web pentru a permite altcuiva să aibă grijă de salvarea adresei.
Pentru spațiul de stocare de pe server, multe cadre de dezvoltare web precum ASP.NET oferă și acces la o "sesiune de utilizatori". Sesiunea poate trăi în memorie sau într-o bază de date, dar un dezvoltator poate stoca informații în sesiune și poate prelua informațiile pentru fiecare solicitare ulterioară. Datele stocate într-o sesiune sunt destinate unui utilizator individual (de fapt, în sesiunea de navigare a utilizatorului) și nu sunt distribuite între mai mulți utilizatori.
Sesiunea de stocare are un model ușor de programare și este bună doar pentru starea de scurtă durată, deoarece în cele din urmă serverul trebuie să presupună că utilizatorul a părăsit site-ul sau a închis browser-ul, iar serverul va renunța la sesiune. Sesiunea de stocare, dacă este stocată în memorie, poate avea un impact negativ asupra scalabilității, deoarece solicitările ulterioare trebuie să se adreseze aceluiași server unde se află datele de sesiune. Unele balansoare de sarcină ajută la susținerea acestui scenariu prin implementarea "sesiunilor lipicioase".
S-ar putea să te întrebi cum un server poate urmări un utilizator să implementeze starea sesiunii. Dacă două cereri ajung la un server, cum știe serverul dacă acestea sunt două solicitări de la același utilizator sau dacă există doi utilizatori diferiți, fiecare făcând o singură cerere?
În primele zile ale web-ului, software-ul de server ar putea avea utilizatori diferențiate prin vizionarea adresei IP a unui mesaj de solicitare. Aceste zile, totuși, mulți utilizatori trăiesc în spatele dispozitivelor utilizând Traducerea adreselor de rețea, iar din acest motiv și din alte motive puteți avea mai mulți utilizatori eficient pe aceeași adresă IP. O adresă IP nu este o tehnică sigură pentru diferențierea utilizatorilor.
Din fericire, există tehnici mai fiabile.
Site-urile web care doresc să urmărească utilizatorii se vor adresa de multe ori fursecuri. Cookie-urile sunt definite de RFC6265 (http://tools.ietf.org/html/rfc6265), iar acest RFC este denumit în mod corespunzător "Mecanismul de gestionare a stării HTTP". Când un utilizator vizitează mai întâi un site web, site-ul poate oferi browserului utilizatorului un cookie utilizând un antet HTTP. Browserul știe apoi să trimită cookie-ul în anteturile fiecărei solicitări suplimentare pe care o trimite pe site. Presupunând că site-ul web a plasat un fel de identificator unic în cookie, atunci site-ul poate urmări acum un utilizator ca el sau ea face cereri și să diferențieze un utilizator de altul.
Înainte de a intra în mai multe detalii despre cum arată cookie-urile și cum se comportă, merită să remarcați câteva limitări. În primul rând, modulele cookie pot identifica utilizatorii în sensul că cookie-ul este diferit de cookie-ul meu, dar modulele cookie nu autentifică utilizatorii. Un utilizator autentificat și-a dovedit identitatea de obicei prin furnizarea de acreditări precum un nume de utilizator și o parolă. Cookie-urile despre care vorbim până acum ne dau un identificator unic pentru a diferenția un utilizator de altul și pentru a urmări un utilizator pe măsură ce se solicită site-ul.
În al doilea rând, deoarece cookie-urile pot urmări ceea ce face un utilizator, ele ridică probleme de confidențialitate în anumite cercuri. Unii utilizatori vor dezactiva cookie-urile în browserele lor, adică browserul va respinge toate cookie-urile unui server care trimite un răspuns. Cookie-urile dezactivate prezintă o problemă pentru site-urile care au nevoie să urmărească utilizatorii, desigur, iar alternativele sunt dezordonate. De exemplu, o abordare a sesiunilor "cookieless" este plasarea identificatorului de utilizator în adresa URL. Modelele cookieless necesită ca fiecare adresă URL pe care un site le dă unui utilizator să conțină identificatorul adecvat, iar adresele URL devin mult mai mari (de aceea această tehnică este denumită adesea tehnica "adaos de grăsime"),.
Atunci când un site dorește să dea unui utilizator un cookie, acesta folosește a Set-Cookie
antet într-un răspuns HTTP.
HTTP / 1.1 200 OK Tip de conținut: text / html; charset = utf-8 Set-Cookie: fname = Scott $ lname = Allen; domeniu = .mywebsite.com; path = / ...
Există trei zone de informații în cookie-ul afișat în acest eșantion. Cele trei zone sunt delimitate prin punct și virgulă (;). Mai întâi, există una sau mai multe perechi de nume-valoare. Aceste perechi de nume-valoare sunt delimitate de un semn de dolar ($) și arată foarte asemănătoare cu modul în care parametrii interogării sunt formatați într-o adresă URL. În cookie-ul de exemplu, serverul a dorit să stocheze numele și prenumele utilizatorului în cookie. A doua și a treia zonă sunt domeniul și calea, respectiv. Vom reveni mai târziu pentru a vorbi despre domeniu și cale.
Un site web poate pune orice informație dorită într-un cookie, deși există o limită de dimensiune de 4 KB. Cu toate acestea, multe site-uri pun doar într-un identificator unic pentru un utilizator, poate un GUID. Un server nu poate avea încredere în nimic stocat pe client decât dacă este securizat criptografic. Da, este posibil să stocați date criptate într-un modul cookie, dar de obicei este mai ușor să stocați un cod.
HTTP / 1.1 200 Set OK-Cookie: GUID = 00a48b7f6a4946a8adf593373e53347c; domeniu = .msn.com; path = /
Presupunând că browserul este configurat să accepte modulele cookie, browserul va trimite cookie-ul la server în fiecare solicitare HTTP ulterioară.
GET ... HTTP / 1.1 Cookie: GUID = 00a48b7f6a4946a8adf593373e53347c; ...
Când ID-ul ajunge, software-ul de servere poate căuta rapid orice date asociate utilizatorilor dintr-o structură de date în memorie, o bază de date sau o memorie cache distribuită. Puteți configura majoritatea cadrelor de aplicații web pentru a manipula modulele cookie și pentru a căuta automat starea sesiunilor. De exemplu, în ASP.NET, Sesiune
Obiectul expune un API ușor pentru citirea și scrierea unei stări de sesiune a utilizatorului. În calitate de dezvoltatori, nu trebuie niciodată să ne facem griji cu privire la trimiterea unui mesaj Set-Cookie
antet sau citirea cookie-urilor primite pentru a găsi starea sesiunilor asociate. În spatele scenei, ASP.NET va gestiona cookie-ul sesiunii.
Sesiune ["firstName"] = "Scott"; // scrie starea sesiunii ... var lastName = Sesiunea ["lastName"]; // citirea starea sesiunii
Din nou, merită subliniat faptul că Nume
și numele de familie
datele stocate în obiectul sesiunii sunt nu intră în cookie. Cookie-ul conține doar un identificator de sesiune. Valorile asociate identificatorului de sesiune sunt sigure pe server. În mod implicit, datele sesiunii intră într-o structură de date în memorie și rămân în viață timp de 20 de minute. Când un cookie de sesiune ajunge într-o cerere, ASP.NET va asocia datele corecte de sesiune cu Sesiune
după găsirea datelor utilizatorului utilizând ID-ul stocat în cookie. Dacă nu există niciun cookie primit cu un ID de sesiune, ASP.NET va crea unul cu a Set-Cookie
antet.
O preocupare de securitate în jurul identificatorilor de sesiune este modul în care pot deschide posibilitatea ca cineva să-i deturneze sesiunea unui alt utilizator. De exemplu, dacă folosesc un instrument ca Fiddler pentru a urmări traficul HTTP, s-ar putea să văd a Set-Cookie
antetul vine de la un server cu Sessionid = 12
interior. S-ar putea să cred că un alt utilizator are deja o Sesiune ID
din 11 și să creați o solicitare HTTP cu acel cod doar pentru a vedea dacă pot fura sau vizualiza codul HTML destinat altui utilizator. Pentru a combate această problemă, majoritatea aplicațiilor web vor folosi numere aleatorii mari ca identificatori (ASP.NET utilizează 120 de biți de aleatorie). Un identificator al sesiunii ASP.NET arată după cum urmează, ceea ce face mai greu să ghiciți cum va arăta ID-ul sesiunii altcuiva.
Set-cookie: ASP.NET_SessionId = en5yl2yopwkdamv2ur5c3z45; path = /; HttpOnly
O altă preocupare de securitate în jurul cookie-urilor este cât de vulnerabile sunt acestea la un atac scripting (XSS). Într-un atac XSS, un utilizator rău intenționează să injecteze codul JavaScript rău intenționat în site-ul altcuiva. În cazul în care celălalt site trimite scriptul malware către utilizatorii săi, scriptul malitios poate modifica sau inspecta și fura informațiile cookie (care pot duce la deturnarea sesiunii sau, mai rău).
Pentru a combate această vulnerabilitate, Microsoft a introdus HttpOnly
steag (văzut în ultimul Set-Cookie
exemplu). HttpOnly
steagul spune agentului utilizator să nu permită codului de script să acceseze cookie-ul. Cookie-ul există pentru "numai HTTP" - adică. pentru a ieși în antetul fiecărui mesaj de solicitare HTTP. Browserele care implementează HttpOnly
nu va permite JavaScript să citească sau să scrie cookie-ul pe client.
Cookie-urile pe care le-am văzut până acum sunt sesiuni cookie. Cookie-urile pentru sesiuni există pentru o singură sesiune de utilizator și sunt distruse atunci când utilizatorul închide browserul. Cookie-uri persistente poate supraviețui unei singure sesiuni de navigare și un agent de utilizator va stoca cookie-urile pe disc. Puteți închide un computer și vă puteți întoarce o săptămână mai târziu, mergeți la site-ul dvs. preferat și un cookie persistent va mai fi acolo pentru prima solicitare.
Singura diferență dintre cele două este că un cookie persistent are nevoie de unul expiră
valoare.
Set-Cookie: nume = valoare; expiră = luni, 09-iulie-2012 21:12:00 GMT
Un modul cookie de sesiune poate adăuga în mod explicit a decarta
atribui unui cookie, dar fără un cookie expiră
valoare, agentul utilizator ar trebui să elimine cookie-ul în orice caz.
Până acum, am spus că odată ce un cookie este setat de un site web, cookie-ul va călători pe site-ul web cu fiecare solicitare ulterioară (presupunând că cookie-ul nu a expirat). Cu toate acestea, nu toate cookie-urile călătoresc pe fiecare site web. Singurele module cookie pe care un agent utilizator trebuie să le trimită unui site sunt cookie-urile furnizate agentului utilizator de către același site. Nu ar avea sens ca cookie-urile de la amazon.com să fie într-o cerere HTTP către google.com. Acest tip de comportament ar putea deschide doar probleme suplimentare legate de securitate și confidențialitate. Dacă setați un cookie într-un răspuns la o solicitare la www.server.com, cookie-ul rezultat va călători numai în cererile la www.server.com.
O aplicație web poate modifica, de asemenea, domeniul de aplicare al unui modul cookie pentru a restricționa cookie-ul la o anumită gazdă sau domeniu și chiar la o anumită cale de resurse. Aplicația web controlează domeniul de aplicare utilizând domeniu
și cale
atribute.
HTTP / 1.1 200 OK Set-Cookie: nume = valoare; domeniu = .server.com; path = / chestii ...
domeniu
atributul permite unui modul cookie să cuprindă subdomeniile. Cu alte cuvinte, dacă setați un cookie de la www.server.com, agentul utilizator va livra cookie-ul numai la www.server.com. Domeniul din exemplul precedent permite, de asemenea, cookie-ului să călătorească către orice adresă URL din domeniul server.com, inclusiv images.server.com, help.server.com și doar server.com. Nu puteți folosi atributul de domeniu pentru a include domenii, așadar setarea domeniului la .microsoft.com într-un răspuns la .server.com nu este legal și agentul de utilizator ar trebui să respingă cookie-ul.
cale
atributul poate restricționa un modul cookie într-o anumită cale de resurse. În exemplul precedent, modulul cookie va călători numai pe un site server.com, la care se îndreaptă adresa URL a solicitării /chestie
, sau o locație dedesubt /chestie
, ca / chestii / imagini
. Setările pentru căi pot ajuta la organizarea cookie-urilor atunci când mai multe echipe construiesc aplicații web pe diferite căi.
Cookie-urile permit site-urilor web să stocheze informații în client și informațiile vor călători înapoi la site-uri în cererile ulterioare. Beneficiile dezvoltării web sunt extraordinare, deoarece cookie-urile ne permit să urmărim ce solicitare aparține acelui utilizator. Dar, cookie-urile au unele probleme pe care le-am atins deja.
Cookie-urile au fost vulnerabile la atacurile XSS așa cum am menționat mai devreme și, de asemenea, primim publicitate proastă când site-urile (în special site-urile de publicitate) utilizează terțe părți cookie pentru a urmări utilizatorii de pe Internet. Mărimile cookie terță parte sunt cookie-urile care se stabilesc dintr-un domeniu diferit de domeniul din bara de adrese a browserului. Terță parte au această posibilitate, deoarece multe site-uri web, atunci când trimite o resursă de pagină înapoi la client, vor include linkuri către scripturi sau imagini de la alte adrese URL. Solicitările care merg către celelalte adrese URL permit celorlalte site-uri să configureze modulele cookie.
De exemplu, pagina de pornire de pe server.com poate include a >