Sesjonshåndtering
Skjulte input felt
Når et CGI-skript blir kalt av en webside med get eller post skal skriptet returnere data. I de situasjonene som interesserer oss er disse dataene en HTML-side og programmet som mottar disse dataene er en nettleser. Vi har da en mulighet for å lage denne returnerte HTML-siden slik at den inneholder skulte felt som sendes til skriptet ved neste forespørsel, uten at brukeren vet det. Det vil si brukeren kan finne det ut hvis han/hun inspiserer kildekoden. Disse skjulet feltene kan akkumulere historien i dialogen, slik at det mottagende skriptet kan reagere basert på denne historien.
Modulen Forms Hidden forklarer dette nærmere i detalj og har et eksempel som demonstrerer bruken av skjulte inputfelt.
Fordelen med skjulte felt er at de er lette å programmere og administrere fra skriptets side. Ulempen er at hukommelsen ikke varer ut over en sammenhengende sesjon. Hvis brukeren går ut av nettleseren slik at vevsiden går tapt, er hukommelsen borte. Vi kan altså ikke komme tilbake til, f.eks. nettbutikken, dagen etter og forvente at vi kan finne igjen vår handlevogn med de tingene vi plukket fram dagen før. Som brukere kan vi bevare historien ved å ta vare på en kopi av vevsiden og starte den opp dagen etter, men dette er en urealistisk forutsetning i en klient-tjener løsning.
localStorage
HTML5 introduserer en mulighet, localStorage, som gjør det mulig på en enkel måte å lagre data som overlever en sesjon. Dette er nærmere omtalt i modulen Skriv og husk . localStorage og localSession er i prinsipp en alternativ form for cookie, se nedenfor, men er langt enklere å programmere.
Cookies
Cookies plasserer også hukommelsen hos klienten, men denne metoden har den egenskapen at hukommelsen i form av en tekst plasseres på klientens harddisk, og er altså ikke avhengig av en sammenhengende nettlesersesjon.
Cookies har også noen ulemper. Brukeren kan bestemme at alle cookies skal avvises. Videre er det slik at en cookie er knyttet til en maskin, ikke en person. Det betyr to ting: en bruker kan ikke ta med seg noen historie over på en annen maskin, og en ny bruker på maskinen som har cookies satt vil overta den forrige personens historie.
Anatomi
En cookie er i praksis en navngitt datastreng som kan følge en klient gjennom en sesjon. Cookies kan også brukes som fundament for autentiseringsløsninger der det er ønskelig med mer finkornet kontroll enn det som er mulig med vanlig HTTP-autentisering.
En webserver kan sende null, én eller flere cookies til en klient via HTTP-headeren. En hver cookie må ha et unikt navn og en verdi. Navnet kan seinere brukes for å hente verdien fra klienten. I tillegg til en verdi kan en cookie ha flere attributter, bl.a.:
- Comment og CommentURL kan brukes for å beskrive hva cookien brukes til.
- Discard indikerer at cookien skal slettes når browseren avsluttes.
- Domain spesifiserer hvilket domene cookien er gyldig i.
- Path spesifiserer hvilken del av kataloghierarkiet på serveren cookien er gyldig i.
- Max-Age bestemmer cookiens levetid (i sekunder).
Cookies i Javascript
Vi ser først på et enkelt eksempel der vi administrer cookies i Javascript. Det vil si at det er klientene som setter en cookie, sjekker om den er satt og, for demonstrasjonens skyld fjerner den. For å få til dette introduserer vi et lite javaskriptbibliotek som kan utføre disse tre funksjonene:
function setCookie(name, value, expires, path, domain, secure) { document.cookie= name + "=" + escape(value) + ((expires) ? "; expires=" + expires.toUTCString() : "") + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + ((secure) ? "; secure" : ""); } function getCookie(name) { var dc = document.cookie; var prefix = name + "="; var begin = dc.indexOf("; " + prefix); if (begin == -1) { begin = dc.indexOf(prefix); if (begin != 0) return null; } else { begin += 2; } var end = document.cookie.indexOf(";", begin); if (end == -1) { end = dc.length; } return unescape(dc.substring(begin + prefix.length, end)); } function deleteCookie(name, path, domain) { if (getCookie(name)) { document.cookie = name + "=" + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + "; expires=Thu, 01-Jan-70 00:00:01 GMT"; } }
Merk at en coookie får en bestemt varighet. Hvis vi ikke sier noe om dette varer cookien så lenge sesjonen varer, dvs. så lenge kllienten kjører. Vi kan sette denne varigheten til et bestemt tidspunkt , om noen dager eller måneder eller sekunder. Parameteren expires i funksjonen setCookie er et Date-object og en aktuelle parameter kans ettes slik:
// set the cookie to last 20 seconds date=new Date(); date.setTime(date.getTime()+(20000)); setCookie("voted","1",date);
Vi bruker denne mot en enkel form der hensikten er at brukeren skal svare på et enkelt spørsmål.
Cookies i Python
Modulen Cookie brukes for behandling av cookies i Python. Legg merke til at modulen bruker en noe forvirrende terminologi: Det som omtales som en cookie er egentlig en samling av cookies, og en morsel er det vanlige mennesker kaller en cookie.
En samling cookies kan opprettes omtrent som dette:
import Cookie c = Cookie.SimpleCookie() c["sesjons-ID"] = "35x84756" c["farge"] = "Gul"
Objektet c inneholder nå to cookies, som kan sendes til klienten slik:
print c.output()
Resultatet blir en tekststreng som kan sendes som del av HTTP-headeren (fvs. før Content-type-linja sendes):
Set-Cookie: farge=Gul; Set-Cookie: sesjons-ID=35x84756;
Vi ser på et eksempel som gjør det samme som eksempelet ovenfor (Javaskripteksempelet). I dette tilfellet gjøre det ingen test på klienten. Det er serveren som både setter og tester cookien.
Pythonkoden er slik:
#! /usr/bin/python import cgitb, cgi, Cookie, os cgitb.enable() """ Check for a cookie and set a cookie """ def makeCookieText(): c = Cookie.SimpleCookie() # A new set of cookies c["voted"] = "1" # New cookie (navn: voted, verdi: 1) c["voted"]["max-age"] = 10 # dropped after 10 seconds cookieText = c.output() # Cookie to text return cookieText #--------------- # what have we got form = cgi.FieldStorage() # first we check input from form foundvalue="0" if form.has_key("transport"): foundvalue=form["transport"].value # assume it is ok to receive this report="Akseptert verdien: "+foundvalue # do we have any cookie set c = Cookie.SimpleCookie() # c is a collection of cookies useit=True try: clientCookieText = os.environ["HTTP_COOKIE"] c.load(clientCookieText) #load cookies if c.has_key("voted"): # the one we are interested in report="Du har allerede registrert ditt bidrag" useit=False except KeyError: # no cookies found pass if useit: # Do whatever we want to du with the received value pass #------------ #return header with new cookie and htmlreport clientCookieText = makeCookieText() print clientCookieText+";" # Cookie-settet sendes til browseren print "Content-type: text/html\n" print""" <html> <head><title>returned</title></head> <body> <p>%s</p> <p>%s</p> </html> """%(report,clientCookieText)