9 – Gestione Sessioni e Cookie
Obiettivo didattico
Capire la differenza tra sessioni e cookie, imparare a creare e gestire sessioni in PHP, usare cookie per persistenza lato client, e mettere in pratica il tutto con un esercizio: implementare un carrello e-commerce semplificato.
1) Differenza tra sessioni e cookie — concetto chiave
-
Cookie
-
Piccoli file (coppie chiave/valore) memorizzati dal browser sul computer dell’utente.
-
Sono inviati automaticamente al server ad ogni richiesta verso il dominio che li ha impostati.
-
Sono utili per persistenza lato client: preferenze tema, tracking, ricordami.
-
Limitazioni: dimensione limitata (~4 KB per cookie, limite totale per dominio variabile), visibili al client (quindi sensibili al furto/modifica se non protetti).
-
-
Sessione
-
Dati memorizzati sul server associati a un identificatore (session id) che il client porta con sé, solitamente tramite un cookie di sessione.
-
Il server mantiene lo stato (es. dati di login, carrello) e il client contiene solo l’ID.
-
Vantaggi: i dati effettivi non sono memorizzati nel browser, maggior sicurezza e possibilità di memorizzare strutture dati complesse.
-
Svantaggi: consumo di risorse server, necessità di gestione della scadenza e di storage scalabile in ambienti distribuiti.
-
Sintesi: cookie = memoria lato client, sessione = memoria lato server + riferimento lato client.
2) Come funziona una sessione (flusso operativo)
-
Il server crea una sessione quando necessario e genera un identificatore unico (session id).
-
Al client viene inviato (di solito) un cookie contenente il session id.
-
Ad ogni richiesta successiva il browser invia quel cookie; il server usa il session id per recuperare i dati della sessione (array, oggetti, ecc.).
-
Quando l’utente effettua il logout o la sessione scade, il server distrugge i dati associati a quell’id.
Elementi pratici da conoscere:
-
session_start()(o equivalente) apre/ristabilisce la sessione. -
Recupero/assegnazione: la sessione è generalmente rappresentata da un array associativo lato server (es.
$_SESSION). -
Terminazione: si devono fornire funzioni per distruggere la sessione in modo sicuro (
session_unset()+session_destroy()e rimozione cookie di sessione).
3) Cookie: parametri importanti e considerazioni di sicurezza
Quando si imposta un cookie bisogna considerare:
-
nome e valore (entità chiave/valore).
-
durata (expire): tempo dopo il quale il cookie viene eliminato (session cookie = scade alla chiusura del browser).
-
path e domain: limitano dove il cookie è valido.
-
secure: se impostato, il cookie viene inviato solo tramite connessioni HTTPS.
-
HttpOnly: se impostato, il cookie non è accessibile via script JavaScript (riduce rischio XSS).
-
SameSite: controlla l’invio del cookie in contesti cross-site (
Lax,Strict,None+Secure).
Buone pratiche:
-
Non mettere dati sensibili non cifrati nei cookie. Se devi memorizzare info sensibili, usa cookie come token che fa riferimento a dati server-side.
-
Impostare
HttpOnlyeSecurequando possibile. -
Usare
SameSiteper mitigare CSRF (Cross-Site Request Forgery).
4) Gestione sicura delle sessioni
Rischi principali:
-
Session fixation: un attaccante fornisce un session id noto alla vittima e poi sfrutta la sessione autenticata.
Mitigazione: rigenerare il session id dopo login (es.session_regenerate_id(true)). -
Session hijacking: furto del session id (es. via XSS o rete non cifrata).
Mitigazione: usare HTTPS, cookieHttpOnly, limitare durata sessione, associare sessione a IP o user agent con attenzione (può causare falsi positivi). -
Scadenza e pulizia: definire timeout di inattività e rimuovere dati obsoleti.
-
Storage lato server: sessioni per siti con più server richiedono storage condiviso (file system condiviso, database, Redis/Memcached). Evitare dipendere solo dal file system locale in cluster.
Best practice operative:
-
Chiamare sempre la funzione di avvio della sessione in testa alla pagina prima di qualsiasi output.
-
Rigenerare l’id dopo l’autenticazione e in situazioni sensibili.
-
Limitare lo scope e la durata della sessione.
-
Distruggere la sessione al logout e cancellare il cookie di sessione.
5) Struttura dati tipica in sessione (esempi concettuali)
Esempi di come si possono organizzare i dati lato sessione (concetto, non codice):
-
Utente loggato:
-
session['user'] = { id: 42, username: 'mario', roles: ['user'] } -
session['last_activity'] = 2025-09-21T11:00:00Z
-
-
Carrello (esempio):
-
session['cart'] = { product_id => { qty: 2, price: 9.90 }, ... } -
Totali calcolati al volo dal server leggendo
session['cart'].
-
-
Token CSRF:
-
session['csrf_token'] = 'random-string'per verificare i POST provenienti dal form.
-
6) Esempio concettuale: ciclo di vita di un carrello semplificato
Flusso utente:
-
Utente visita sito — il server avvia/chiama la sessione.
-
Quando l’utente aggiunge un prodotto al carrello, il server aggiorna
session['cart'](incrementa quantità, aggiunge prodotto). -
Nel checkout, il server calcola totali, imposte, spedizione leggendo la sessione; dopo pagamento finale, si può svuotare la sessione o mantenerne una parte per storico.
-
Se l’utente non è loggato, la sessione tiene lo stato del carrello. Se successivamente effettua il login, si può fondere il carrello della sessione con quello salvato nel DB (merge).
Esempio di struttura (valori d’esempio):
-
session['cart'] = { 101: { name: "T-shirt", qty: 2, price: 15.00 }, 204: { name: "Cappello", qty: 1, price: 12.50 } } -
Totale calcolato: (2 * 15.00) + (1 * 12.50) = 42.50
7) Esercizio svolto: carrello e-commerce semplificato (concettuale, passo-passo)
Obiettivo: descrivere la logica completa senza mescolare codice, così da poterla implementare facilmente.
Requisiti funzionali
-
Aggiungere prodotto al carrello.
-
Rimuovere prodotto o decrementare quantità.
-
Visualizzare il carrello con voci, quantità e subtotali.
-
Svuotare il carrello al completamento dell’ordine.
-
Conservare il carrello tra le pagine usando sessione.
Struttura dati (lato sessione)
-
session['cart']mappaproduct_id→ oggetto{ qty, unit_price, name }.
Operazioni (algoritmo)
-
Aggiungi prodotto
-
Ricevo
product_id,qty(default 1). -
Se
product_idgià presente insession['cart'], incrementoqty. -
Altrimenti aggiungo nuova voce con
qtyeunit_pricepreso dal catalogo. -
Aggiorno
session['last_update'] = now.
-
-
Rimuovi prodotto
-
Ricevo
product_id. -
Se presente in
session['cart']rimuovo la voce o decremento laqtyse richiesto.
-
-
Visualizza carrello
-
Itero su
session['cart'], calcolosubtotalper voce =qty * unit_price. -
Sommo i subtotali per ottenere
cart_total. -
Mostro
cart_total, numero di articoli (somma delle quantità) e dettagli delle voci.
-
-
Checkout
-
Verifico che il carrello non sia vuoto.
-
Applico controlli (disponibilità, prezzi correnti, sconti).
-
Se tutto ok, creo l’ordine nel database e svuoto il carrello in sessione (oppure lo salvo nello storico dell’utente).
-
Esempio numerico (simulazione)
-
Azione: aggiungi
product_id = 101(T-shirt, unit_price = 15.00), qty = 2.-
session['cart']diventa{101: {qty:2, unit_price:15.00, name:"T-shirt"}}.
-
-
Azione: aggiungi
product_id = 204(Cappello, unit_price = 12.50), qty = 1.-
session['cart']ora contiene 2 voci.
-
-
Visualizza carrello:
-
Voce 101: subtotal = 2 * 15.00 = 30.00
-
Voce 204: subtotal = 1 * 12.50 = 12.50
-
Totale carrello = 42.50
-
Considerazioni pratiche
-
Sempre ricalcolare i prezzi dal catalogo al momento del checkout (evitare di fidarsi solo del valore in sessione).
-
Usare token CSRF per proteggere azioni POST (aggiungi/rimuovi).
-
Consentire agli utenti autenticati di salvare il carrello nel database per ripristino futuro su altri device.
8) Errori comuni e debugging
-
Sessione non inizializzata: chiamare la funzione di avvio della sessione prima di leggere/scrivere dati.
-
Output prima della session_start(): l’invio di output prima della definizione dei cookie o dell’avvio della sessione impedisce la corretta impostazione del cookie di sessione (headers already sent).
-
Dimenticare di rigenerare l’ID dopo il login → rischio session fixation.
-
Non chiudere / non distruggere la sessione al logout → rischio che una macchina condivisa mantenga una sessione attiva.
-
Dipendenza dallo storage locale su cluster → sessioni non condivise tra nodi (usare storage condiviso come Redis).
Per debug:
-
Loggare
session_id()e il contenuto disession(in ambiente di sviluppo) per verificare flusso stato. -
Verificare cookie nel browser (devtools → Application / Storage) per controllare scadenze e flag.
9) Domande di verifica rapida
-
Qual è la differenza fondamentale tra cookie e sessione?
Risposta: cookie = dati memorizzati nel browser (lato client); sessione = dati memorizzati sul server associati a un session id trasportato dal client. -
Perché rigenerare l’id di sessione dopo il login?
Risposta: per mitigare session fixation; garantire che un id precedente non utilizzabile dall’attaccante rimanga valido dopo autenticazione. -
Quali flag di cookie aumentano la sicurezza?
Risposta:HttpOnly,Secure, eSameSite(insieme aiutano a ridurre i rischi XSS/CSRF e furto su connessioni non TLS). -
Dove conviene memorizzare sessioni in un ambiente con più server?
Risposta: in uno storage condiviso (Redis, Memcached, DB o filesystem condiviso) per rendere le sessioni accessibili da tutti i nodi.
10) Estensioni e miglioramenti pratici
-
Persistenza cross-device: salvare carrelli di utenti autenticati nel DB e fare merge con quello in sessione.
-
Utilizzare JWT (JSON Web Token) per autenticazione stateless quando appropriato (diverso modello rispetto a sessioni server-side).
-
Implementare limitazione della durata della sessione e logout automatico per inattività.
-
Monitorare e invalidare sessioni sospette (es. cambio IP frequente o attività anomale).

Nessun commento:
Posta un commento