Sessioni
HTTP è un protocollo stateless, ma quasi tutte le applicazioni hanno bisogno di mantenere uno stato tra una richiesta e l'altra, ad esempio il contenuto di un carrello della spesa. A questo serve una sessione. Vediamo
- come utilizzare le sessioni
- come evitare conflitti di denominazione
- come impostare la scadenza
Quando si utilizzano le sessioni, ogni utente riceve un identificatore unico, chiamato ID di sessione, che viene passato in un cookie. Questo serve come chiave per i dati di sessione. A differenza dei cookie, che sono memorizzati sul lato browser, i dati di sessione sono memorizzati sul lato server.
La sessione viene configurata nella configurazione; la scelta del tempo di scadenza è importante.
La sessione è gestita dall'oggetto Nette\Http\Session,
che si ottiene passandoglielo tramite dependency injection. Nei
presentatori è sufficiente chiamare $session = $this->getSession()
.
Avvio della sessione
Per impostazione predefinita, Nette avvia automaticamente una sessione nel momento in cui si inizia a leggere da essa o a
scrivere dati su di essa. Per avviare manualmente una sessione, utilizzare $session->start()
.
All'avvio della sessione, PHP invia le intestazioni HTTP che influiscono sulla cache, vedere session_cache_limiter, ed eventualmente un cookie con l'ID della sessione. Pertanto, è sempre necessario avviare la sessione prima di inviare qualsiasi output al browser, altrimenti verrà lanciata un'eccezione. Pertanto, se si sa che una sessione verrà utilizzata durante il rendering della pagina, è bene avviarla manualmente prima, ad esempio nel presentatore.
In modalità sviluppatore, Tracy avvia la sessione perché la utilizza per visualizzare le barre di reindirizzamento e di richiesta AJAX nella barra Tracy.
Sezione
In PHP puro, l'archivio dei dati di sessione è implementato come un array accessibile tramite una variabile globale
$_SESSION
. Il problema è che le applicazioni sono normalmente costituite da un certo numero di parti indipendenti e
se tutte hanno a disposizione solo uno stesso array, prima o poi si verificherà una collisione di nomi.
Nette Framework risolve il problema dividendo l'intero spazio in sezioni (oggetti Nette\Http\SessionSection). Ogni unità utilizza quindi la propria sezione con un nome unico e non si verificano collisioni.
La sezione viene ottenuta dal gestore di sessione:
$section = $session->getSection('unique name');
Nel presentatore è sufficiente chiamare getSession()
con il parametro:
// $this è il presentatore
$section = $this->getSession('unique name');
L'esistenza della sezione può essere verificata con il metodo $session->hasSection('unique name')
.
È molto facile lavorare con la sezione stessa usando i metodi set()
, get()
e
remove()
:
// scrittura di una variabile
$section->set('userName', 'franta');
// lettura di una variabile, restituisce null se non esiste
echo $section->get('userName');
// rimozione di una variabile
$section->remove('userName');
È possibile utilizzare il ciclo foreach
per ottenere tutte le variabili della sezione:
foreach ($section as $key => $val) {
echo "$key = $val";
}
Come impostare la scadenza
La scadenza può essere impostata per singole sezioni o anche per singole variabili. Possiamo lasciare che il login dell'utente scada tra 20 minuti, ma ricordare il contenuto di un carrello.
// la sezione scadrà dopo 20 minuti
$section->setExpiration('20 minutes');
Il terzo parametro del metodo set()
è usato per impostare la scadenza delle singole variabili:
// La variabile 'flash' scade dopo 30 secondi
$section->set('flash', $message, '30 seconds');
Ricordare che il tempo di scadenza dell'intera sessione (vedere la configurazione della sessione) deve essere uguale o superiore al tempo impostato per le singole sezioni o variabili.
La cancellazione della scadenza precedentemente impostata può essere ottenuta con il metodo removeExpiration()
.
La cancellazione immediata dell'intera sezione sarà assicurata dal metodo remove()
.
Eventi $onStart, $onBeforeWrite
L'oggetto Nette\Http\Session
ha gli eventi
$onStart
e $onBeforeWrite
, quindi si possono aggiungere callback che vengono richiamati dopo l'avvio
della sessione o prima che questa venga scritta su disco e poi terminata.
$session->onBeforeWrite[] = function () {
// scrivere i dati nella sessione
$this->section->set('basket', $this->basket);
};
Gestione della sessione
Panoramica dei metodi della classe Nette\Http\Session
per la gestione delle sessioni:
start(): void
Avvia una sessione.
isStarted(): bool
La sessione è stata avviata?
close(): void
Termina la sessione. La sessione termina automaticamente al termine dello script.
destroy(): void
Termina e cancella la sessione.
exists(): bool
La richiesta HTTP contiene un cookie con un ID di sessione?
regenerateId(): void
Genera un nuovo ID di sessione casuale. I dati rimangono invariati.
getId(): string
Restituisce l'ID della sessione.
Configurazione
Configuriamo la sessione nella configurazione. Se si sta scrivendo un'applicazione che non usa un contenitore DI, usare questi metodi per configurarla. Devono essere chiamati prima di avviare la sessione.
setName(string $name): static
Imposta il nome del cookie utilizzato per trasmettere l'ID di sessione. Il nome predefinito è PHPSESSID
. È utile
se si eseguono diverse applicazioni sullo stesso sito.
getName(): string
Restituisce il nome del cookie di sessione.
setOptions(array $options): static
Configura la sessione. È possibile impostare tutte le direttive di sessione PHP (in formato camelCase, ad esempio
scrivere savePath
invece di session.save_path
) e anche readAndClose.
setExpiration(?string $time): static
Imposta il tempo di inattività dopo il quale la sessione scade.
setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null): static
Imposta i parametri per i cookie. È possibile modificare i valori dei parametri predefiniti in configuration#Session cookie.
setSavePath(string $path): static
Imposta la directory in cui sono memorizzati i file di sessione.
setHandler(\SessionHandlerInterface $handler): static
Imposta un gestore personalizzato, vedere la documentazione di PHP.
Sicurezza prima di tutto
Il server presume di comunicare con lo stesso utente finché le richieste contengono lo stesso ID di sessione. Il compito dei meccanismi di sicurezza è quello di garantire che questo comportamento funzioni davvero e che non ci sia la possibilità di sostituire o rubare un identificatore.
Ecco perché Nette Framework configura correttamente le direttive PHP per trasferire l'ID di sessione solo nei cookie, per evitare l'accesso da JavaScript e per ignorare gli identificatori nell'URL. Inoltre, nei momenti critici, come il login dell'utente, genera un nuovo ID di sessione.
La funzione ini_set è utilizzata per la configurazione di PHP, ma sfortunatamente il suo uso è proibito da alcuni servizi di web hosting. Se è il vostro caso, provate a chiedere al vostro fornitore di hosting di autorizzare questa funzione o almeno di configurare correttamente il suo server.