I det här kapitlet ska vi titta på säkerhetsaspekterna i HTTP, inklusive hur man identifierar användare, hur HTTP-autentisering fungerar, och varför vissa scenarier kräver HTTPS (säker HTTP). Under vägen kommer vi också att lära oss lite om hur man hanterar tillstånd med HTTP.
HTTP är ett statlöst protokoll, vilket innebär att varje begäran-svarstransaktion är oberoende av tidigare eller framtida transaktioner. Det finns inget i HTTP-protokollet som kräver att en server behåller information om en HTTP-begäran. Allt servern behöver göra är att skapa ett svar för varje förfrågan. Varje förfrågan kommer att bära all information som en server behöver för att skapa svaret.
HTTP: s statslösa karaktär är en av drivkraften i webens framgång. De lagrade tjänster som vi tittade på i det föregående kapitlet, tjänster som cachning, är alla möjliga (eller åtminstone enklare) eftersom varje meddelande innehåller all information som krävs för att bearbeta meddelandet. Proxyservrar och webbservrar kan inspektera, transformera och cache meddelanden. Utan cachning kunde webben inte skala för att möta kraven på Internet.
Men de flesta av de webbapplikationer och tjänster vi bygger ovanpå HTTP är mycket statliga.
En bankansökan vill att en användare ska logga in innan han tillåter användaren att se hans eller hennes kontorelaterade resurser. Eftersom varje statslös förfrågan anländer till en privat resurs vill ansökan säkerställa att användaren redan är autentiserad. Ett annat exempel är när användaren vill öppna ett konto och fylla i formulär i en tre sidors guide. Applikationen kommer att vilja se till att förstasidan av guiden är klar innan användaren kan skicka in den andra sidan.
Lyckligtvis finns det många alternativ för lagring av tillstånd i en webbapplikation. Ett tillvägagångssätt är att bädda in staten i de resurser som överförs till klienten, så att allt tillstånd som krävs av ansökan kommer att gå tillbaka till nästa förfrågan. Detta tillvägagångssätt kräver vanligtvis vissa dolda inmatningsfält och fungerar bäst för kortlivat tillstånd (som staten behöver för att flytta genom en tre-sidig guide). Inbäddningstillstånd i resursen håller hela staten inuti HTTP-meddelanden, så det är ett mycket skalbart tillvägagångssätt, men det kan komplicera applikationsprogrammeringen.
Ett annat alternativ är att lagra staten på servern (eller bakom servern). Det här alternativet är nödvändigt för tillstånd som måste vara på länge. Låt oss säga att användaren skickar ett formulär för att ändra sin e-postadress. E-postadressen måste alltid vara associerad med användaren, så programmet kan ta den nya adressen, validera adressen och lagra adressen i en databas, en fil eller ringa en webbtjänst för att låta någon annan ta hand om att spara adressen.
För lagring av server-sidor ger många webbutvecklingsramar som ASP.NET också tillgång till en "användarsession". Sessionen kan leva i minnet eller i en databas, men en utvecklare kan lagra information i sessionen och hämta informationen vid varje efterföljande förfrågan. Data som lagras i en session är scoped till en enskild användare (faktiskt till användarens surfningssession) och delas inte bland flera användare.
Session lagring har en enkel programmeringsmodell och är bara bra för kortlivet tillstånd, eftersom servern till slut måste anta att användaren har lämnat webbplatsen eller stängt webbläsaren och servern kommer att kasta sessionen. Sessionslagring, om den lagras i minnet, kan påverka skalbarheten negativt eftersom efterföljande förfrågningar måste gå till exakt samma server där sessionsdata finns. Vissa belastningsbalanser hjälper till att stödja detta scenario genom att genomföra "klibbiga sessioner".
Du kanske undrar hur en server kan spåra en användare för att implementera sessionstillstånd. Om två förfrågningar kommer till en server, hur känner servern om det är två förfrågningar från samma användare, eller om det finns två olika användare, var och en gör en enda förfrågan?
I de tidiga dagarna på webben kan serverprogramvaran ha differentierade användare genom att titta på IP-adressen till ett förfrågningsmeddelande. Dessa dagar lever dock många användare bakom enheter som använder Network Address Translation, och av detta och andra skäl kan du få flera användare effektivt på samma IP-adress. En IP-adress är inte en tillförlitlig teknik för differentiering av användare.
Lyckligtvis finns det mer tillförlitliga tekniker.
Webbplatser som vill spåra användare kommer ofta att vända sig till småkakor. Cookies definieras av RFC6265 (http://tools.ietf.org/html/rfc6265), och denna RFC är lämpligt betecknad "HTTP State Management Mechanism". När en användare först besöker en webbplats kan webbplatsen ge användarens webbläsare en cookie med hjälp av en HTTP-rubrik. Webbläsaren vet då att skicka kakan i rubrikerna för varje ytterligare begäran som den skickar till webbplatsen. Om du antar att webbplatsen har placerat någon form av unik identifierare i cookien, kan webbplatsen nu spåra en användare eftersom han eller hon gör förfrågningar och differentiera en användare från en annan.
Innan vi får veta mer om hur cookies ser ut och hur de beter sig är det värt att notera några begränsningar. Först kan cookies identifiera användare i den meningen att din cookie är annorlunda än min cookie, men cookies godkänner inte användarna. En autentiserad användare har visat sin identitet vanligen genom att tillhandahålla legitimationsuppgifter som ett användarnamn och lösenord. De kakor vi pratar om hittills ger oss bara en unik identifierare för att differentiera en användare från en annan, och spåra en användare, eftersom förfrågningar görs på webbplatsen.
För det andra, eftersom cookies kan spåra vad en användare gör, tar de upp privatlivets oro i vissa kretsar. Vissa användare kommer att inaktivera cookies i sina webbläsare, vilket innebär att webbläsaren kommer att avvisa alla cookies som en server skickar i ett svar. Inaktiverade cookies presenterar ett problem för webbplatser som behöver spåra användare, och alternativen är röriga. Till exempel är ett tillvägagångssätt för "cookieless sessions" att placera användaridentifieraren i webbadressen. Cookieless-sessioner kräver att varje webbadress som en webbplats ger till en användare innehåller den korrekta identifieraren, och webbadresserna blir mycket större (varför denna teknik kallas ofta "fet webbadress" -teknik).
När en webbplats vill ge en användare en kaka använder den en Set-Cookie
header i ett HTTP-svar.
HTTP / 1.1 200 OK Innehållstyp: text / html; charset = utf-8 Set-Cookie: fname = Scott $ lname = Allen; domän = .mywebsite.com; path = / ...
Det finns tre områden med information i kakan som visas i detta prov. De tre områdena är avgränsade av semikolon (;). För det första finns det ett eller flera namnvärdespar. Dessa namnvärdespar är avgränsade av ett dollartecken ($) och ser mycket ut som hur parametrarna formateras till en webbadress. I exemplet cookie ville servern spara användarens förnamn och efternamn i kakan. Det andra och tredje området är respektive domänen och sökvägen. Vi ringer tillbaka senare för att prata om domän och sökväg.
En webbplats kan lägga all information som den gillar i en kaka, även om det finns en storleksbegränsning på 4 KB. Men många webbplatser lägger bara in en unik identifierare för en användare, kanske en GUID. En server kan aldrig lita på allt som lagras på klienten om det inte är kryptografiskt säkrat. Ja, det är möjligt att lagra krypterad data i en cookie, men det är vanligtvis lättare att lagra ett ID.
HTTP / 1.1 200 OK Set-Cookie: GUID = 00a48b7f6a4946a8adf593373e53347c; domän = .msn.com; path = /
Om du antar att webbläsaren är konfigurerad för att acceptera cookies skickar webbläsaren cookien till servern i varje efterföljande HTTP-begäran.
GET ... HTTP / 1.1 Kaka: GUID = 00a48b7f6a4946a8adf593373e53347c; ...
När ID-numret anländer kan serverns programvara snabbt slå upp eventuella tillhörande användardata från en data-struktur, databas eller distribuerad cache i minnet. Du kan konfigurera de flesta webbapplikationsramar för att manipulera cookies och automatiskt söka upp sessionstillstånd. Till exempel i ASP.NET, den Session
objektet avslöjar ett enkelt API för att läsa och skriva en användares sessionsläge. Som utvecklare behöver vi aldrig oroa oss för att skicka en Set-Cookie
rubrik eller läsa inkommande cookies för att hitta den associerade sessionen. Bakom kulisserna hanterar ASP.NET session kakan.
Session ["firstName"] = "Scott"; // skriva sessionstillstånd ... var lastName = Session ["lastName"]; // läsesessionstillstånd
Återigen är det värt att påpeka att förnamn
och efternamn
data som lagras i sessionsobjektet är går inte in i kakan. Kakan innehåller bara en sessionidentifierare. Värdena som är associerade med sessionidentifieraren är säkra på servern. Sessionsdata går som standard in i en minnesdatastruktur och fortsätter att leva i 20 minuter. När en session cookie kommer in i en förfrågan kommer ASP.NET att associera rätt sessiondata med Session
objekt efter att ha hittat användarens data med hjälp av det ID som lagrats i cookien. Om det inte finns någon inkommande cookie med ett session-ID skapar ASP.NET en med a Set-Cookie
rubrik.
Ett säkerhetsproblem kring sessionsidentifierare är hur de kan öppna möjligheten för att någon kapar en annan användares session. Om jag till exempel använder ett verktyg som Fiddler för att spåra HTTP-trafik kan jag se en Set-Cookie
header kommer från en server med Sessionid = 12
inuti. Jag kan gissa att någon annan användare redan har en sessionid
av 11 och skapa en HTTP-förfrågan med det här ID-en för att se om jag kan stjäla eller visa HTML som är avsedd för någon annan användare. För att bekämpa detta problem använder de flesta webbapplikationer stora slumptal som identifierare (ASP.NET använder 120 bitar av slumpmässighet). En ASP.NET-sessionidentifierare ser ut som följer, vilket gör det svårare att gissa vad någon annans sessions-ID skulle se ut som.
Set-Cookie: ASP.NET_SessionId = en5yl2yopwkdamv2ur5c3z45; path = /; Httponly
Ett annat säkerhetsproblem kring kakor är hur sårbart de är för en cross-site scripting attack (XSS). I en XSS-attack sprutar en skadlig användare ondskanlig JavaScript-kod till någon annans webbplats. Om den andra webbplatsen skickar det skadliga skriptet till sina användare kan det skadliga skriptet ändra eller inspektera och stjäla information om kakor (vilket kan leda till att kapaciteten sjunker eller är sämre).
För att bekämpa denna sårbarhet introducerade Microsoft Httponly
flagga (ses i det sista Set-Cookie
exempel). De Httponly
flaggan berättar att användaragenten inte tillåter skriptkod att komma åt cookien. Cookien existerar endast för "HTTP" -i.e. att resa ut i rubriken för varje HTTP-förfrågan. Webbläsare som implementerar Httponly
tillåter inte JavaScript att läsa eller skriva kakan på klienten.
De kakor vi hittat hittills är session cookies. Session-cookies finns för en enda användarsession och förstörs när användaren stänger webbläsaren. Persistent cookies kan överleva en enda surfa och en användaragent lagrar kakorna till disken. Du kan stänga av en dator och komma tillbaka en vecka senare, gå till din favoritwebbplats, och en fortsatt cookie kommer fortfarande att finnas där för den första förfrågan.
Den enda skillnaden mellan de två är att en bestående en kaka behöver en Utgår
värde.
Set-Cookie: namn = värde; löper ut = måndag, 09-juli-2012 21:12:00 GMT
En session cookie kan uttryckligen lägga till en Kassera
attribut till en kaka men utan en Utgår
värdet bör användaragenten i alla händelser kassera kakan.
Hittills har vi sagt att när en kaka ställs in av en webbplats, kommer kakan att resa till hemsidan med varje efterföljande förfrågan (förutsatt att kakan inte har löpt ut). Dock går inte alla cookies till varje webbplats. De enda cookies som en användaragent ska skicka till en webbplats är cookies som ges till användaragenten på samma webbplats. Det skulle inte vara meningsfullt för cookies från amazon.com att vara i en HTTP-begäran till google.com. Denna typ av beteende kan bara öppna ytterligare säkerhets- och sekretessproblem. Om du ställer in en cookie som svar på en begäran till www.server.com, kommer den resulterande cookien endast att resa i begäran till www.server.com.
En webbapplikation kan också ändra räckvidden för en cookie för att begränsa cookien till en viss värd eller domän, och även till en specifik resursväg. Webapplikationen styr räckvidden med hjälp av domän
och väg
attribut.
HTTP / 1.1 200 OK Set-Cookie: namn = värde; domän = .server.com; path = / saker ...
De domän
attributet tillåter en cookie att spänna underdomäner. Med andra ord, om du ställer in en cookie från www.server.com, levererar användaragenten endast cookien till www.server.com. Domänen i det föregående exemplet tillåter också att cookien kan resa till vilken URL som helst i server.com-domänen, inklusive images.server.com, help.server.com och helt enkelt server.com. Du kan inte använda domänattributet för att spänna domäner, så inställningen av domänen till .microsoft.com som svar på .server.com är inte laglig och användaragenten bör avvisa cookien.
De väg
attributet kan begränsa en cookie till en specifik resursväg. I det föregående exemplet kommer kakan bara att resa till en server.com-webbplats när begäran om webbadressen pekar på /grejer
, eller en plats nedanför /grejer
, tycka om / stuff / bilder
. Baninställningar kan hjälpa till att organisera cookies när flera lag bygger webbapplikationer på olika vägar.
Cookies tillåter webbplatser att lagra information i klienten och informationen kommer att återvända till sidorna i efterföljande förfrågningar. Fördelarna med webbutveckling är enorma, eftersom cookies tillåter oss att hålla reda på vilken förfrågan som tillhör vilken användare. Men, kakor har några problem som vi redan har berört.
Cookies har varit sårbara för XSS-attacker som vi tidigare nämnde, och får också dålig publicitet när webbplatser (särskilt reklamwebbplatser) använder cookies från tredje part att spåra användare över Internet. Cookies från tredje part är cookies som ställs in från en annan domän än domänen i webbläsarens adressfält. Cookies från tredje part har denna möjlighet eftersom många webbplatser, när de skickar en sidresurs tillbaka till klienten, kommer att innehålla länkar till skript eller bilder från andra webbadresser. Förfrågningarna som går till de andra webbadresserna tillåter andra webbplatser att ställa in cookies.
Till exempel kan hemsidan på server.com innehålla en >