Web-1/Gebruikers en sessies

Uit Inf2019
Naar navigatie springen Naar zoeken springen
Web1
Netwerken

Zie ook Regels en richtlijnen
Zie ook Artikelen bewerken

Gebruikers, sessies en cookies

In de server moet je http-requests van verschillende gebruikers kunnen onderscheiden. Dat kan alleen als de client (browser) informatie over de gebruiker meestuurt in elk request: de informatie over de gebruiker moet van de client komen. HTTP biedt hiervoor het cookie-mechanisme:

  • de server krijgt informatie van de client (browser), bijvoorbeeld de naam van de gebruiker in een opgestuurd formulier;
  • de server stuurt in een response een cookie, met bijvoorbeeld de naam van de gebruiker, naar de client (browser);
  • de client slaat het cookie lokaal op en stuurt dit automatisch met elk http-request naar deze server mee.
    • een cookie in de browser is gekoppeld aan een domein (van de server): een server krijgt alleen de eigen cookies weer opgestuurd.
client state client action http server action
user=? get form ==> GET (form-url; cookie: user=?) ==> handle GET (with user=?)
user=? handle response <== response (form) <==
.
user=? send form ==> POST (form: username="Hans") ==> handle POST-form
handle response <== response (cookie: user=Hans) <== set cookie: "user=Hans"
user=Hans
user=Hans follow link(url) ==> GET (url; cookie: user=Hans) ==> handle GET (with user=Hans)

Het http-protocol gebruikt een speciale header voor het versturen van de cookies.

Eerste experiment met cookies: cookietest

Cookies test

NodeRed-code: /Nodered-cookietest

Login-form:

<!doctype html>
<html>
    <head>
        <title>Login</title>
    </head>
    <body>
        <h3>Please login</h3>
        <form method="post" action="/login-form">
            Name:
            <input type="text" name="username">
            <button type="submit">Send</button>
        </form>
    </body>
</html>

Process-login-form (set username cookie):

var username = msg.payload.username || "";

msg.cookies = {user: username};
msg.user = username;
return msg;

Process-cookietest (get username from cookie):

msg.user = msg.req.cookies.user || "";
return msg;

Test-page:

<!DOCTYPE html>
<html>
  <head>
	<title>Cookie test</title>
  </head>
  <body>
    <h3>Welcome</h3>
    <p>Welcome {{user}}!</p>
    <a href="/login">Change username</a>
  </body>
</html>

In dit voorbeeld gebruiken we cookies om de naam van de gebruiker bij te houden. Hiermee kunnen we een pagina altijd aan de juiste gebruiker koppelen, ook als er meerdere gebruikers tegelijk actief zijn.

Deze flow is een kleine variatie op de flow die we eerder gezien hebben.

  • de client vraagt de html-pagina op, met daarin het login-formulier;
  • de client stuurt het ingevulde formulier naar de server;
  • de server ontvangt het login-formulier met daarin de naam van de gebruiker: msg.payload.username;
  • bij het ontvangen van dit login-formulier stuurt de server in de response een cookie user met de naam van de gebruiker. In NodeRed geef je deze nieuwe of veranderde cookies op in de message (msg). Een cookie is een naam/waarde paar; voorbeeld:
msg.cookies = {user: msg.payload.username};
  • bij het afhandelen van een http-request in de server zijn de ontvangen cookies te vinden in msg.req.cookies. In dit geval is de naam van de gebruiker te vinden als msg.req.cookies.user. We gebruiken vaak de onderstaande constructie: in dat geval heeft username altijd een gedefinieerde waarde, ook als het betreffende cookie niet gedefinieerd is.
var username = msg.req.cookies.user || "";

Opdrachten

  • kopieer bovenstaande flow naar NodeRed (op een nieuwe pagina; eventueel via /Nodered-cookietest);
  • bekijk de inhoud van de verschillende nodes (zie ook hierboven): waar wordt het cookie gezet, waar wordt de waarde van het cookie gebruikt?
  • voeg een debug-node toe aan de http-input nodes. Laat deze debug-node de binnengekomen cookies afdrukken (msg.req.cookies).
    • je kunt hiervoor een enkele debug-node gebruiken, of een debug-node per http-input node: in het laatste geval kun je in het debug-venster nog nagaan van welke input-node dit cookie afkomstig is.
  • bekijk de cookies in de browser-ontwikkelaarstools.
    • hoe wordt een cookie verstuurd naar de server? (Netwerk-tab, response)
    • hoe wordt een cookie ontvangen van de server? (Netwerk-tab, request)
    • welke cookies zijn opgeslagen in de browser? (Application-tab: Storage; of Opslag-tab)
      • je kunt een cookie hier ook aanpassen; probeer dit.
  • voeg aan het cookie dat gezet wordt in de server een maximale levensduur toe (van een paar minuten):

msg.cookies = {username: {value: msg.payload.username, maxAge: 180}};

  • Controleer of het cookie verdwijnt (in de browser).
    • wat betekent dit voor het gebruik van een cookie in een gebruikerspagina? Je moet eigenlijk altijd controleren of een cookie gezet is.
  • je kunt een cookie verwijderen (in NodeRed) door dit de waarde null te geven, bijvoorbeeld: msg.cookie = {user: null};.
    • ga in de functie set-username na of de username in het formulier leeg is (lege string); verwijder in dat geval het user-cookie.
    • controleer in de browser dat het cookie verdwijnt als de gebruiker bij de login niets invult.

Meer over cookies

Cookies in de browser

Je kunt als gebruiker de cookies die een server in je browser opslaat bekijken via de gebruikers-voorkeuren van die browser. Je kunt eventueel ook cookies verwijderen.

Levensduur van cookies; verwijderen door server

Een cookie heeft in de browser een bepaalde maximale geldigheid. De server geeft deze geldigheid op bij het opsturen van het cookie. Als de server niets opgeeft, is het cookie alleen voor de sessie geldig (totdat het venster of de browser afgesloten wordt). Een cookie kan ook veel langer geldig zijn: in dat geval bewaart de browser het cookie in een bestand in het filesysteem. Dit cookie blijft dan bewaard, ook als de browser stopt of de computer uitgeschakeld wordt. Dit noemen we wel persistente opslag. Als gebruiker kun je de cookies in de browser (-voorkeuren) bekijken en eventueel verwijderen.

  • de server kan meerdere eigenschappen meegeven bij een cookie, zoals de maximale levensduur (maxAge, in seconden). Voorbeeld:
msg.cookies = {user: {value: msg.payload.username, maxAge: 3600}};
  • de server kan een cookie verwijderen voor dit de waarde null te geven:
msg.cookies = {user: null};

Hoe kunnen cookies gebruikt worden om je surf-gedrag bij te houden?

  • "tracking" cookies: cookies van andere website dan waar de pagina zelf vandaan komt (vgl. advertenties, figuren)
  • server kan nagaan van welke pagina een request komt (via request-header "referrer")
  • in veel gevallen heeft de server geen cookies nodig - zeker niet als geen perfectie gevraagd wordt.

Anoniem gebruik van een website

P.M.

Kan de server cookies van de client vertrouwen?

P.M.

Cookies in client-side scripts

Je kunt in JavaScript in de browser de cookies lezen, via document.cookie. Dit is één lange string, met daarin de verschillende cookies als name=value-paren, gescheiden door ;. Met de volgende functie kun je deze wat toegankelijker maken, als een JavaScript-object:

function getCookies() {
  var cookies = document.cookie.split(";");
  var cookiesMap = {};
  cookies.forEach(function (s){
      var x = s.split("="); // format: name = value
      cookiesMap[x[0]] = x[1];
  });
  return cookiesMap;
}