Questa cosa continuo a scordarmela, battendoci il testone ogni nuova applicazione che faccio. Ora me la scrivo qui e non me la dimentico più (sì, certo).
Il problema in due parole: fai login sulla tua applicazione in PHP e dopo 20 minuti di inattività di trovi di nuovo buttato fuori e devi rifare login. Che noia! Voglio fare in modo che la mia sessione di lavoro duri molto ma molto di più. Ma come? A questo proposito occorre sapere un paio di cosette…
Affinché la propria applicazione si “ricordi” il login, sappiamo bene che si utilizza quasi sempre il concetto di SESSIONE. Fin qui niente di nuovo (faccio giusto per mettere sul banchetto tutti i pezzetti). La gestione delle sessioni in PHP – generalmente – utilizza un cookie, il quale serve per conoscere la corrispondenza tra la richiesta HTTP (dove viaggia il cookie) e la sessione (salvata sul server). Il contenuto del cookie di sessione potrebbe essere, per esempio, il nome del file con i dati che devono rimanere semipermanenti (salvataggio dello stato dell’applicazione).
La prima cosa da modificare, se si vuole che la sessione duri un tempo da noi scelto, è dunque la durata della validità di questo cookie. Per default questo cookie scade alla chiusura del browser (evento che si chiama, giusto per fare confusione, “end of session“). Usando le apposite funzioni PHP session_set_cookie_params() e session_name() si cambia la durata del cookie a nostro piacimento e magari anche il nome, giusto per non avere sempre il solito PHPSESSID.
Riproviamo e dopo un po’ che lavoriamo, magari su più progetti, ci accorgiamo che… il cookie scade effettivamente tra 10 giorni, ma la sessione continua (ci sembra!) a buttarci fuori troppo spesso!
L’inghippo sta in un altro parametro della sessione: gc_maxlifetime (maledetto!). Questo valore indica al php ogni quanto far scadere le sessioni non più utilizzate. Il concetto è: in un’applicazione molto trafficata, viene creato un file di sessione per ogni nuovo utente (google compreso, se non si fa attenzione). Se qualcuno, ogni tanto, non si prendesse la briga di fare pulizia di questi file che magari nessuno usa più da mesi, beh, immaginate cosa potrebbe succedere (e i gli utilizzatori di Ruby On Rails credo sappiano di cosa sto parlando…).
Il PHP ha un suo sistema “interno” di pulizia. Il prefisso “gc” di quella variabile di configurazione infatti sta proprio per garbage collector. Ogni volta che si richiede l’accesso ad una sessione, il PHP verifica se qualche file non è magari troppo vecchio e dunque da cancellare. Ma “troppo vecchio” quanto? Beh, statisticamente vecchio quanto indica appunto il gc_maxlifetime (l’algoritmo è un pochino più complesso, ma è sufficiente capire il concetto). Il lifetime di default è proprio 1440 secondi, i famosi 20 minuti. Se non accediamo per 20 minuti (circa) alla nostra sessione ci sono buone probabilità che il PHP decida di cancellare il nostro file. E noi ci troveremo di nuovo sloggati.
Prima abbiamo dunque sistema il nostro cookie; adesso usiamo la ini_set() per portare a 86400 e rotti il nostro session.gc_maxlifetime.
Ci rimettiamo al lavoro felici quando un bel giorno ci accorgiamo che… siamo stati buttati fuori! ARGH! Perché!?
Il problema è che l’impostazione fatta tramite la ini_set() all’interno di uno script vale SOLO per quello script (e tutti quelli da esso inclusi, ovviamente). Non vale per TUTTI gli script di tutte le altre applicazioni che risiedono su quella macchina, applicazioni che condividono tutte la stessa directory delle sessioni. È dunque sufficiente che uno di questi script venga eseguito una volta, e la sua session_start() deciderà che il file di sessione dell’altra applicazione (ma lui che ne sa?) è scaduto e deve essere cancellato.
A questo punto ci sono un paio di opzioni (tre o quattro, in verità):
- imposto il mio gc_maxlifetime a livello globale (php.ini) così che valga per tutte le applicazioni
- modifico il session.save_path di ogni applicazione che gira sullo stesso server in modo che ognuna gestisca solo i SUOI file di sessione e così possa decidere indipendentemente anche il proprio gc_lifetime
- modifico l’handler delle sessioni, spostandole magari in un database (session_set_save_handler()) o mi scrivo il mio sistema di garbage collector delle stesse (script in cron, per esempio…)
7 Responses to “Per chi scade la sessione”
a me non risulta molto chiaro il concetto : "Non vale per TUTTI gli script che posso avere sulla mia macchina di sviluppo o di produzione."
This comment was originally posted on FriendFeed
è un pezzo che non uso php ma dovrebbe essere che siccome il path per i file di sessione è comune a tutte le applicazioni (siti?) che girano su uno stesso server (a meno che non lo configuri tu — vedi fine post), se nell’applicazione X vuoi che le sessioni vengano cancellate ogni 10 giorni mentre in Y (che non hai scritto tu) vengono cancellate ogni 5, finisce che le sessioni di X vengono piallate prima a causa di gc_maxlifetime di Y
This comment was originally posted on FriendFeed
alieb, non hai letto il mio articolo eh? :) Arrivo alle stesse conclusioni, ma essendo un articoletto divulgativo spiego anche perché in maniera un po’ più discorsiva.
This comment was originally posted on FriendFeed
sì che l’ho letto, ho cercato di rispiegarlo a modo mio perché marigrace non aveva capito
This comment was originally posted on FriendFeed
alieb, ops. Scusami… ho coda di paglia più lunga del mondo, sappilo.
This comment was originally posted on FriendFeed
cmq, grazie ho aggiornato un po’ il testo :)
This comment was originally posted on FriendFeed
adesso è chiarissimo Claudio
This comment was originally posted on FriendFeed
Additional comments powered by BackType