2011-09-21 17 views
7

Ho problemi con il sito PHP Eseguo al lavoro dove gli utenti vengono disconnessi dopo alcuni minuti (l'ora esatta varia, ma è abbastanza frequente da essere un problema), indipendentemente dal fatto che hanno usato attivamente il sito o no.Le sessioni PHP scadono presto

Il problema è che non riesco a riprodurre questo problema, se accedo come utenti con lo stesso browser non riesco a disconnettermi, il che suggerisce che non si tratta di una rottura completa del sito. Purtroppo non ho accesso ai computer degli utenti per eseguire alcun software di sniffing del traffico.

Le cose che ho già controllato sono:

  • chiedendo agli utenti di provare i vari browser. Ciò non sembra risolvere il problema e non è comunque una soluzione a lungo termine, in quanto non è possibile dettare quali browser utilizzeranno i clienti.
  • L'ora del server è corretta e in linea con le macchine dell'utente.
  • L'utente Apache viene eseguito come autorizzato a scrivere nella cartella della sessione e posso vedere i file di sessione creati e i loro tempi di modifica aggiornati.
  • Non vengono utilizzate funzioni di buffer di output.
  • Il problema sta accadendo su una varietà di pagine che sembrano non avere nulla in comune (cioè non è che tutti usano AJAX, o aggiornano il database o qualche altro motivo).
  • Gli utenti accedono al loro account solo da una macchina, ovvero non lavorano un po 'sul portatile, passano al desktop e si domandano perché sono stati disconnessi dal loro laptop (non permettiamo più login simultanei per lo stesso utente).

Le impostazioni di sessione in PHP sono le impostazioni predefinite di Debian e non sono state modificate in un file .htaccess o altrove. I principali sono:

session.cookie_lifetime 0 
session.gc_divisor 100 
session.gc_maxlifetime 1440 
session.gc_probability 0 
session.save_handler files 
session.save_path /var/lib/php5 
session.use_cookies On 

Debian cancella sessioni attraverso un processo di cron, invece di utilizzare garbage collector di PHP, che è il motivo per cui gc_probability è impostato a 0. La versione di PHP stiamo correndo è: PHP 5.2.6-1 + lenny13 con Suhosin-Patch 0.9.6.2 (cli) (ultima versione di Lenny, aggiorneremo presto Squeeze ma non penso che sia la causa del problema).

Utilizziamo Zend_Session per gestire le sessioni e un'istanza di Zend_Session_Namespace viene creata una volta su ogni pagina, chiamando quindi automaticamente session_start(). Le sessioni sono cancellati chiamando Zend_Session :: destroy() nella pagina di logout, quindi gli unici modi in cui un utente deve essere registrato fuori sono:

  • Se si fa clic esplicitamente il link di logout (abbiamo registro quando questo accade e doesn Sembra che il browsing stia precompilando la pagina e quindi effettui il logout dell'utente.
  • Se lascia la sessione inattiva per più di 24 minuti, a quel punto Debian probabilmente cancellerà la propria sessione (c'è un cron job che viene eseguito ogni mezz'ora eliminando tutte le sessioni che non sono state modificate per oltre 24 minuti).
  • Se chiudono il browser, il loro cookie di sessione con una scadenza pari a 0 verrà cancellato.

I controlli per vedere se un utente è connesso in sono:

  • Hanno una sessione valida (controllato da vedere se siamo in grado di accedere a $ zsession-> user_id).
  • C'è una riga nella tabella delle sessioni che ha un ID utente e un ID sessione corrispondenti e questo è stato aggiornato l'ultima volta meno di un'ora fa. Cancelliamo questa riga al logout in modo che nessuno possa accedere a tale account senza accedere.

Qualcuno può suggerire altre cose che posso provare?

Edit: Alcune cose aggiuntive che ho provato sulla base dei commenti rimasto:

  • Impostazione session.cookie_domain: Questo sembra avere un comportamento molto strano in PHP. Se non imposto questa variabile e la lasciamo come predefinita di '' (stringa vuota), allora una richiesta per www.domain.com produrrà un cookie di www.dominio.com. Tuttavia, se imposto cookie_domain su "www.dominio.com", il dominio per il cookie è ".www.dominio.com" (nota punto iniziale, che significa valido per tutto ciò che si trova sotto www.domain.com, ad esempio sito secondario.www .dominio.com).
  • Impostazione session.cookie_lifetime: PHP non sembra aggiornare il tempo di scadenza su ogni richiesta, quindi se imposto cookie_lifetime a 3600 il cookie scadrà un'ora dopo che l'utente visita per la prima volta il sito, anche se l'accesso e l'utilizzo costante .

Edit 2: Sulla base di altre cose persone hanno chiesto:

  • Il sito è ospitato in un data center, in una VLAN separata. Nessuno che accede al sito si trova sulla stessa rete del sito.
  • Non è utilizzata l'autenticazione IP, né l'indirizzo IP del client utilizzato in alcuna parte del processo di sessione (ad esempio, non associamo la sessione a un indirizzo IP e blocchiamo l'utente se la successiva richiesta proviene da un IP diverso).
+0

L'ultima volta che ho avuto un problema simile, mi mancava di gestire correttamente le sessioni in un certo file php (tutti gli altri file erano ok). Il risultato è stato che la sessione è diventata invalida dopo che l'utente ha tentato di uscire da quella determinata pagina in modo da essere disconnesso dopo diversi minuti a seconda di quando ha navigato sulla pagina. Non vederlo come una soluzione. Vedi come un suggerimento in cui potresti cercare alcuni errori. In bocca al lupo! ^^ – Marco

+0

I fusi orari (o il tempo sbagliato del server) possono causare problemi in alcuni casi. – Smar

+1

@Smar Può ma ho fatto esplicitamente dire "L'ora del server è corretta e in linea con le macchine dell'utente". – pwaring

risposta

1

Alla fine, la risposta è stata di appena rottami sessioni e scrivere il mio codice biscotto molto semplice che si differenzia dalle sessioni nei seguenti modi:

  1. Stores un hash (po 'come un ID di sessione) nella database piuttosto che nei file.
  2. Imposta il cookie che scade tra 3600 secondi da ora (aggiornato su ogni pagina) anziché 0 secondi (quest'ultimo sembrava causare problemi agli utenti di IE, sebbene non potessi mai replicarlo).
  3. Invia l'intestazione del cookie solo quando l'utente esegue l'accesso o ha effettuato l'accesso.

Non è una situazione ideale in quanto c'è qualche reinventare la ruota in corso, ma la mia piccola soluzione sembra funzionare in cui le sessioni di PHP non ha fatto, e avere un sito di lavoro è la cosa più importante.

0

è il vostro sito su domini diversi? ad esempio domain.com, www.domain.com, sottodominio.dominio.com? se alcune pagine vengono reindirizzate a un dominio diverso (www è considerato un sottodominio diverso) rispetto alle sessioni non funzionerà quando l'indirizzo cambia

MODIFICA: È necessario riprodurre il problema. Chiedi ai tuoi clienti che tipo di browser usano, quali azioni fanno fino a quando non vengono disconnessi, stanno visualizzando lo stesso ip per il sito come fai tu? (ovvero siete entrambi in reti esterne o entrambi nella stessa rete con il sito)

Quando riesci a trovare il problema, controlla le intestazioni di richiesta/risposta quando la sessione funziona, e anche quando non funziona e poi confrontare.

+0

PHP imposterà effettivamente il cookie di sessione per tutti i sottodomini: 'Set-Cookie \t PHPSESSID = 0a4ogbefeptfndukol3pjl7tg4; percorso = /; domain = .thesite.com'. Nota il punto davanti al nome del dominio. –

+0

In realtà PHP non imposta il cookie di sessione per tutti i sottodomini: Set-Cookie: PHPSESSID = 428d4be9caca21acc558c0510f22717b; percorso = /; secure Se guardo il cookie in Firefox, è impostato su www.domain.com (reindirizziamo qualsiasi richiesta di dominio.com a www.dominio.com). – pwaring

+0

Quale versione di PHP stai usando perché nel mio l'output sopra è visibile? –

0

la sessione.gc_maxlifetime è impostata su 1440 ms che è solo 1,44 secondi. non dovrebbe essere 1440000 ms = 24 minuti?

+1

'session.gc_maxlifetime' è impostato in secondi. Quindi 1440 per 24 minuti è corretto. – Marco

+1

sei sicuro che non ci siano altri script con una durata di sessione inferiore? perché viene eseguito lo script con la vita più bassa. –

+1

gc_maxlifetime è impostato a livello globale e non sovrascritto in nessuno degli script PHP. Tutte le funzioni di gestione delle sessioni vengono eseguite in un unico file che è incluso in ogni pagina. – pwaring

0

Si potrebbe provare a impostare session.use_only_cookies su un valore di 1 e session.cookie_lifetime su un valore di 1440 secondi.

+0

per 'session.cookie_lifetime' 0 indica il browser per eliminare il cookie quando è chiusa la finestra che per cookie di sessione è l'ideale. –

+1

Certo che è l'ideale, ma per esempio se si lavora sotto un controller di dominio di Windows che imposta diritti specifici per i browser, la regola non deve essere garantita per funzionare. Ho avuto il problema sotto un controller di dominio che una finestra popup all'interno della stessa sessione ha distrutto il cookie di sessione. Dopo aver impostato la durata in modo esplicito, ho potuto risolvere questo problema. – Marco

+0

Non ho sentito parlare del problema del controller di dominio, immagino che potrebbe essere la soluzione. Farò un tentativo e vedrò cosa succede, anche se non sono sicuro che PHP aggiorni il cookie di sessione su ogni pagina, quindi c'è il rischio che il cookie possa scadere dopo 24 minuti, anche se l'utente è ancora attivo. – pwaring

3

Debian elimina sessioni attraverso un processo di cron, invece di utilizzare garbage collector di PHP

che è molto strano - e quello che è il codice che viene eseguito nel processo di cron?

Noi cancelliamo questa riga al logout

vi consiglio di tenere questo per, diciamo, 2 giorni dopo che la sessione è scaduta/è soppressa (ma la bandiera è come morto nel punto in cui attualmente cancellare esso). Inoltre, inizia a registrare l'ID di sessione nei log del tuo server web.

+0

Non è particolarmente strano, Debian ha usato quel metodo per anni. L'esecuzione effettiva del codice è: 09,39 * * * * root [-x/usr/lib/php5/maxlifetime] && [-d/var/lib/php5] && find/var/lib/php5/-type f -cmin + $ (/ usr/lib/php5/maxlifetime) -delete – pwaring

+0

e hai controllato quali output/usr/lib/php5/maxlifetime? – symcbean

+0

Sì, emette 24 (che è quello che mi aspetterei). Il lavoro cron funziona sicuramente correttamente e elimina solo i file di sessione che non sono stati acceduti per 24 minuti. – pwaring

1

penso che si conta modificare il valore della

session.gc_maxlifetime 

Ho anche affrontato lo stesso problema. Ho passato molto tempo su questo, quindi chiedo al mio fornitore di servizi web e, quando ha ottenuto il permesso, ha cambiato quella valle. Ora funziona bene.

+0

È già impostato su 1440 secondi o 24 minuti, ma gli utenti vengono disconnessi molto prima di allora. – pwaring

1

Ci sono altre applicazioni php in esecuzione sullo stesso sistema (con diversi vhosts, ad esempio?)? Stanno anche salvando le sessioni in/var/lib/php5?

In tal caso, e una di queste app ha una soglia di raccolta dati obsoleti in bassa sessione, trasporteranno i file di sessione della tua app.

Faccio un sacco di sviluppo ZF, e se sto usando sessioni basate su filesystem, li blocco in applicazioni/dati/sessione al posto del sistema predefinito.

+0

C'è una sola applicazione sul sistema, diversa da un paio di siti di test ma hanno tutti la stessa soglia GC. – pwaring

0

Alla fine ho deciso di inviare un'intestazione Set-Cookie su ogni richiesta di pagina, simile a quanto suggerito da FlyBy in uno dei commenti. Il relativo codice/logica ora è (ammesso session_start() è già stato chiamato):

$this->session_name = session_name(); 
$update_cookie = isset($_COOKIE[$this->session_name]); // Check if cookie already set, as PHP will send the first Set-Cookie when the session is started 
$this->logged_in = $this->checkSession(); // Function which checks whether a valid (i.e. not timed-out) session row exists in the DB 
if ($this->logged_in) { 
    $this->updateSession(); // Update the session row to the current time 

    if ($update_cookie) { 
    // Update the cookie expiry only if it existed before the login check 
    setcookie($this->session_name, $_COOKIE[$this->session_name], $this->time + 3600, '/'); 
    } 
} 

Io non sono sicuro del perché questo ha funzionato, ma non ho avuto un successivo reclamo e il numero di accessi è sceso drasticamente (non ci sono più accessi nei log per lo stesso utente in pochi minuti l'uno dall'altro).

Tuttavia, a un certo punto probabilmente riscriverò il codice per utilizzare solo una riga del database e un cookie sul client, perché la funzionalità di sessione in PHP ha così tante variabili che è estremamente difficile capire quale sia la causa del problema e la gestione dei cookie di sessione è leggermente diversa da come vengono gestiti i normali cookie. In particolare, devi stare attento con la funzione setcookie, perché il percorso predefinito per i cookie di sessione avviati da PHP è '/', ma il valore predefinito per setcookie è il percorso della directory corrente e questi non saranno necessariamente uguali.

+0

Rottami che, a quanto pare, il problema sta ancora accadendo, e ho esaurito completamente le idee. – pwaring