2010-06-11 9 views
72

La nostra applicazione Django ha i seguenti requisiti di gestione delle sessioni.Come scadere della sessione a causa di inattività in Django?

  1. Le sessioni scadono quando l'utente chiude il browser.
  2. Le sessioni scadono dopo un periodo di inattività.
  3. Rileva quando una sessione scade a causa di inattività e visualizza un messaggio appropriato all'utente.
  4. Avvisa degli utenti di una sessione imminente alcuni minuti prima della fine del periodo di inattività. Insieme all'avviso, fornire agli utenti un'opzione per estendere la sessione.
  5. Se l'utente sta lavorando su un'attività commerciale lunga all'interno dell'app che non prevede l'invio di richieste al server, la sessione non deve scadere.

Dopo aver letto la documentazione, il codice Django e alcuni post di blog relativi a questo, ho trovato il seguente approccio di implementazione.

Requisito 1
Questo requisito è facilmente implementata impostando SESSION_EXPIRE_AT_BROWSER_CLOSE su True.

Requisito 2
ho visto alcune raccomandazioni di usare SESSION_COOKIE_AGE per impostare il periodo di scadenza della sessione. Ma questo metodo ha i seguenti problemi.

  • La sessione scade sempre alla fine del SESSION_COOKIE_AGE anche se l'utente sta usando attivamente l'applicazione. (Questo può essere evitato impostando la sessione scadenza a SESSION_COOKIE_AGE su ogni richiesta utilizzando un middleware personalizzato o salvando la sessione su ogni richiesta impostando SESSION_SAVE_EVERY_REQUEST su true. Ma il prossimo problema è inevitabile a causa dell'uso di SESSION_COOKIE_AGE.)

  • A causa del funzionamento dei cookie, SESSION_EXPIRE_AT_BROWSER_CLOSE e SESSION_COOKIE_AGE si escludono a vicenda, ovvero il cookie scade alla chiusura del browser o alla scadenza specificata. Se SESSION_COOKIE_AGE viene utilizzato e l'utente chiude il browser prima che il cookie scada, il cookie viene mantenuto e la riapertura del browser consentirà all'utente (oa chiunque altro) nel sistema senza essere nuovamente autenticato.

  • Django si basa solo sul cookie presente per determinare se la sessione è attiva. Non controlla la data di scadenza della sessione memorizzata con la sessione.

Il seguente metodo potrebbe essere utilizzato per implementare questo requisito e per risolvere i problemi sopra menzionati.

  • Non impostare SESSION_COOKIE_AGE.
  • Impostare la data di scadenza della sessione come "ora corrente + periodo di inattività" su ogni richiesta.
  • Sovrascrivere process_request in SessionMiddleware e verificare la scadenza della sessione. Scarta la sessione se è scaduta.

Requisito 3
Quando si rileva che la sessione è scaduta (nel SessionMiddleware personalizzato sopra), impostare un attributo in merito alla richiesta di indicare la sessione di scadenza. Questo attributo può essere utilizzato per visualizzare un messaggio appropriato all'utente.

Requisito 4
Usa JavaScript per rilevare inattività dell'utente, fornire l'avvertimento e anche un'opzione per estendere la sessione. Se l'utente desidera estendere, inviare un impulso keep-alive al server per estendere la sessione.

Requisito 5
Usa JavaScript per rilevare l'attività degli utenti (durante l'operazione di business a lungo) e inviare impulsi mantenere vivo al server per evitare di scadere della sessione.


L'approccio di implementazione di cui sopra sembrano molto elaborato e mi chiedevo se ci potrebbe un metodo più semplice (in particolare per il requisito 2).

Eventuali approfondimenti saranno molto apprezzati.

+1

+1 per fornire una soluzione dettagliata – Don

+1

"A causa del funzionamento dei cookie, SESSION_EXPIRE_AT_BROWSER_CLOSE e SESSION_COOKIE_AGE si escludono a vicenda, ovvero il cookie scade alla chiusura del browser o alla scadenza specificata.Se viene utilizzato SESSION_COOKIE_AGE e l'utente chiude il browser prima che il cookie scada, il cookie viene mantenuto e la riapertura del browser consentirà all'utente (oa chiunque altro) di accedere al sistema senza essere nuovamente autenticato. " Correggimi se sbaglio, ma questo non sembra più essere vero nelle nuove versioni di Django? (Almeno 1.5+) –

+0

C'è un middleware che può fare ciò di cui hai bisogno. [su github] (https://github.com/subhranath/django-session-idle-timeout) e [su pypi] (http://pypi.python.org/pypi/django-session-idle-timeout/1.3 .1) – gbutler

risposta

38

Ecco un'idea ... Scade la sessione sul browser chiusa con l'impostazione SESSION_EXPIRE_AT_BROWSER_CLOSE. Quindi imposta un timestamp nella sessione ad ogni richiesta in questo modo.

request.session['last_activity'] = datetime.now() 

e aggiungere un middleware per rilevare se la sessione è scaduta. qualcosa di simile dovrebbe gestire l'intero processo ...

from datetime import datetime 
from django.http import HttpResponseRedirect 

class SessionExpiredMiddleware: 
    def process_request(request): 
     last_activity = request.session['last_activity'] 
     now = datetime.now() 

     if (now - last_activity).minutes > 10: 
      # Do logout/expire session 
      # and then... 
      return HttpResponseRedirect("LOGIN_PAGE_URL") 

     if not request.is_ajax(): 
      # don't set this for ajax requests or else your 
      # expired session checks will keep the session from 
      # expiring :) 
      request.session['last_activity'] = now 

Poi devi solo fare alcuni URL e punti di vista per restituire i dati relativi alle chiamate Ajax per quanto riguarda la scadenza della sessione.

quando l'utente sceglie di "rinnovare" la sessione, per così dire, tutto quello che dovete fare è impostare requeset.session['last_activity'] al tempo corrente di nuovo

Ovviamente questo codice è solo l'inizio ... ma dovrebbe ottenere voi sulla strada giusta

+0

Sono solo scettico qui, ma non credo che il 'se non request.is_ajax()' sia completamente sicuro. Non è possibile che qualcuno che riceve una sessione prima della scadenza parodia/invii una chiamata ajax e mantenga la sessione in corso? –

+2

@ notbad.jpeg: in generale, "attività" è facilmente falsificabile.Qualcuno che ottiene la sessione e continua a inviare richieste è solo attivo. – RemcoGerlich

+0

Questa è un'ottima risposta. Il middleware è uno strumento molto sottoutilizzato nello sviluppo di Django. –

25

django-session-security fa proprio questo ...

... con un ulteriore requisito: se il server non risponde o un attaccante staccato il collegamento a Internet: per la scadenza in ogni caso.

Disclaimer: Mantengo questa app. Ma Sono stato a guardare questa discussione per molto, molto tempo :)

+1

cool app - ben progettato e ben costruito. bel codice pulito ... grazie. – nicorellius

+1

Anche regolarmente aggiornato - grazie jpic – datakid

+0

Se l'utente chiude il browser o la scheda (senza disconnettersi) quando se ne va, obbliga ancora l'utente a disconnettersi? Gestisce questa condizione? – waterkinq

3

Nella prima richiesta, è possibile impostare la scadenza sessione come

self.request.session['access_key'] = access_key 
self.request.session['access_token'] = access_token 
self.request.session.set_expiry(set_age) #in seconds 

e quando si utilizza l'access_key e il token,

try: 
    key = self.request.session['access_key'] 
except KeyError: 
    age = self.request.session.get_expiry_age() 
    if age > set_age: 
     #redirect to login page 
+0

Up votato per la mancanza di commenti da downvoter. – Ruraj

9

Un modo semplice per soddisfare la tua seconda esigenza sarebbe impostare il valore SESSION_COOKIE_AGE nelle impostazioni.py ad una quantità adeguata di secondi. Per esempio:

SESSION_COOKIE_AGE = 600  #10 minutes. 

Tuttavia, solo facendo questo la sessione scade dopo 10 minuti se l'utente espone una certa attività. Per far fronte a questo problema, il tempo di scadenza può essere rinnovata automaticamente (per altri 10 minuti extra) ogni volta che l'utente esegue ogni tipo di richiesta con la seguente frase:

request.session.set_expiry(request.session.get_expiry_age()) 
8

Sono appena abbastanza nuovo per usare Django.

ho voluto fare la sessione scade se l'utente connesso in prossimità del browser o sono in stand-by (timeout di inattività) per un certo periodo di tempo. Quando ho cercato su Google per capire, questa domanda di SOF è venuta per prima. Grazie a una bella risposta, ho cercato le risorse per capire come funzionano i middleware durante il ciclo di richiesta/risposta in Django. È stato molto utile

Stavo per applicare il middleware personalizzato nel mio codice dopo la risposta in alto qui. Ma ero ancora un po 'sospettoso perché la migliore risposta qui è stata modificata nel 2011. Ho avuto più tempo per cercare un po' dai risultati di ricerca recenti e ho trovato un modo semplice.

SESSION_EXPIRE_AT_BROWSER_CLOSE = True 
SESSION_COOKIE_AGE = 10 # set just 10 seconds to test 
SESSION_SAVE_EVERY_REQUEST = True 

Non ho controllato altri browser ma Chrome. 1. Una sessione è scaduta quando ho chiuso un browser anche se SESSION_COOKIE_AGE è stato impostato. 2. Solo quando ero inattivo per più di 10 secondi, una sessione è scaduta. Grazie a SESSION_SAVE_EVERY_REQUEST, ogni volta che si verifica una nuova richiesta, salva la sessione e scade il timeout degli aggiornamenti

Per modificare questo comportamento predefinito, impostare l'impostazione SESSION_SAVE_EVERY_REQUEST su True. Se impostato su True, Django salverà la sessione nel database su ogni singola richiesta.

Si noti che il cookie di sessione viene inviato solo quando una sessione è stato creato o modificato. Se SESSION_SAVE_EVERY_REQUEST è True, il cookie di sessione verrà inviato ad ogni richiesta.

Allo stesso modo, la scade parte di un cookie di sessione viene aggiornata ogni volta che il cookie di sessione viene inviato.

django manual 1.10

Ho appena lascio risposta così che alcune persone che è una sorta di nuovo in Django come me non si trascorre molto tempo per scoprire la soluzione come un modo che ho fatto.

+0

Tu l'uomo !!! Grazie per la tua ricerca –

Problemi correlati