Sapere come gestire la sessione HTTP è di estrema importanza se un sito web deve identificare gli utenti, allo scopo di rispondere alla diverse richieste in modo appropriato. Le nozioni base necessarie per muovere i primi passi in questa direzione sono ampiamente documentate sul web, quello che manca, a volte, è la spiegazione dettagliata di come server e client riescano a condividere la medesima sessione HTTP. Non si tratta "solo" di un cavillo tecnico, perché spesso è proprio l'ignoranza di ciò che avviene dietro le quinte a portare lo sviluppatore alla crisi di nervi. Proviamo a rimediare fornendo alcuni esempi pratici, riferiti ad un ipotetico sito PHP su Apache.

Abbiamo già visto che il protocollo HTTP è stateless, ovvero dopo ogni singola comunicazione (i.e. la request e la corrispondente response) il canale di trasmissione si chiude: la prossima volta che server e client continueranno la conversazione sarà di fatto una nuova trasmissione. Occorre quindi uno stratagemma per consentire al server di capire che la trasmissione successiva proviene dallo stesso client. Il meccanismo più comune è quello della sessione HTTP: possiamo pensare alla sessione HTTP come ad un codice unico assegnato dal server al client. Il meccanismo è simile a quello che si usa al supermercato: strappiamo un numeretto e lo mettiamo in tasca, quando il panettiere-server chiamerà il nostro numero, saremo identificati dal numero che abbiamo in mano.

Un server assegna gli ID delle sessioni in modo simile, con la differenza che gli ID delle sessioni sono codici alfa-numeri di almeno 20 o 30 caratteri. Inoltre, prima che lo stesso server si ritrovi ad usare lo stesso ID di sessione potrebbero passare decenni: l'ID della sessione può quindi essere considerato unico nell'ambito dello stesso contesto (il server che lo assegna).

Abbiamo detto che il server deve assegnare l'ID della sessione al browser, cosa facile da mettere in pratica: il browser ha chiesto qualcosa al server, quindi comunicare un ID è semplice, perché basta “allegarlo” in qualche modo alla risposta da mandare al browser. Ma come fa il browser a farsi riconoscere la volta successiva, ovvero: come deve comunicare l'ID di sessione al server?

Il metodo più usato è quello di scrivere l'ID della sessione all'interno di un cookie (per una breve introduzione ai cookies vedi qui). Questo è spesso uno degli aspetti che sfuggono a chi si approccia all'argomento la prima volta, ovvero

l'ID della sessione HTTP è il valore di uno specifico cookie

Esistono alcune eccezioni, ma quanto scritto sopra è vero nella grande maggioranza dei casi. Per verificarlo proviamo a scrivere in una pagina PHP queste due righe di codice

 <?php

print_r($_COOKIE);

echo '<br/>Session name = '.session_name() ;

?>

se l'ID della nostra sessione HTTP è memorizzata all'interno di un cookie, allora una delle chiavi dell'array $_COOKIE coinciderà con il nome della sessione.

L'esempio dovrebbe chiarire il rapporto tra cookies e sessione HTTP: quando settiamo o leggiamo dei cookies, potrebbe capitare di trovarci sempre un cookie “in più”, che in PHP per default si chiama PHPSESSID (avrà un nome diverso se rinominiamo la sessione usando session_name()). Il valore di questo cookie dovrebbe coincidere esattamente con l'ID della sessione in corso: quindi tutto a posto, è giusto che sia così.

La relazione tra cookies e sessione spiega anche perché, se (prima o poi) pensiamo di autenticare l'utente, è buona norma assegnare subito la data di scadenza del cookie della sessione, ad esempio

 session_name('my_web_site');

// Making the cookie live for 24 hours

session_set_cookie_params(24*60*60);

session_start();

Se non settiamo subito la data di scadenza, pensando di farlo solo quando l'utente effettuerà il login, rischiamo di non riuscire a gestire correttamente la funzione “ricordami”. Il motivo sarà più chiaro tra poco. La funzione PHP session_start() va solitamente inserita in ogni pagina, scrivendola ad esempio nell'header del sito. Se ci pensiamo un attimo è logico intuire che questa funzione non si comporti sempre allo stesso modo, ma agisca diversamente a seconda della situazione, ovvero

  • E' invocata al momento di iniziare una nuova sessione
  • E' invocata al momento di continuare la sessione precedente

Si tratta insomma di una funzione “intelligente”, capace di adattarsi alla specifica situazione. Consideriamo un utente registrato sul nostro sito che navighi un po' di pagine pubbliche (sempre sul nostro sito) prima di autenticarsi. Durante la navigazione anonima egli userà sempre lo stesso ID di sessione, che resterà invariato dopo il login. Se l'utente si autentica spuntando la casella “ricordami”, noi vogliamo fare in modo che l'ID di sessione rimanga lo stesso anche al prossimo collegamento, cosa che potrebbe avvenire dopo qualche ora o qualche giorno. E' quindi bene centralizzare la configurazione della sessione in un'unica pagina (il solito header), in modo da poter stabilire la durata della funzione “ricordami” senza doverci ricordare dove e come autentichiamo l'utente. Questa scelta non crea alcun problema agli utenti guest, anzi: la loro navigazione resterà anonima anche se utilizzano lo stesso ID di sessione visita dopo visita. Saranno forse un po' “meno anonimi”, ma questo solitamente reca più vantaggi che svantaggi.

Concludiamo ricordando alcuni altri aspetti associati alla sessione HTTP:

  • I dati della sessione sono sul server, non sul client! Quello che viene scritto nel cookie della sessione è quasi sempre solo l'ID della sessione. Tutte le variabili di sessione associate a quell'ID sono sul server. Possiamo pensare all'ID della sessione come il PIN del bancomat: l'utente conosce il PIN, ma i soldi sono comunque in banca, al sicuro (si spera)
  • Se non precisiamo la data di scadenza della sessione, per default questa scadrà quando viene chiuso il broswer. E' per questo motivo che è necessario impostare una scadenza di almeno qualche giorno nel caso volessimo poi aggiungere la casellina “ricordami”

Queste nozioni ci torneranno utili quando ci occuperemo di autenticare gli utenti in PHP, cosa di cui parleremo nella prossime puntate. Buona sessione (di lavoro) a tutti!