2010-06-11 49 views
72

Nuestra aplicación Django tiene los siguientes requisitos de gestión de sesión.¿Cómo caducar la sesión debido a inactividad en Django?

  1. Las sesiones caducan cuando el usuario cierra el navegador.
  2. Las sesiones caducan después de un período de inactividad.
  3. Detecta cuando una sesión caduca debido a inactividad y muestra el mensaje apropiado al usuario.
  4. Advierta a los usuarios de una vencimiento inminente de la sesión unos minutos antes del final del período de inactividad. Junto con la advertencia, brinde a los usuarios la opción de extender su sesión.
  5. Si el usuario está trabajando en una actividad comercial larga dentro de la aplicación que no implica solicitudes que se envían al servidor, la sesión no debe exceder el tiempo de espera.

Después de leer la documentación, el código de Django y algunas publicaciones de blog relacionadas con esto, he presentado el siguiente enfoque de implementación.

Requisito 1
Este requisito se implementa fácilmente mediante el establecimiento de SESSION_EXPIRE_AT_BROWSER_CLOSE en True.

Requisito 2
he visto algunas recomendaciones para utilizar SESSION_COOKIE_AGE para establecer el periodo de caducidad de sesión. Pero este método tiene los siguientes problemas.

  • La sesión siempre expira al final de la SESSION_COOKIE_AGE incluso si el usuario está utilizando activamente la aplicación. (Esto puede evitarse configurando el vencimiento de la sesión en SESSION_COOKIE_AGE en cada solicitud utilizando un middleware personalizado o guardando la sesión en cada solicitud configurando SESSION_SAVE_EVERY_REQUEST en verdadero. Pero el siguiente problema es inevitable debido al uso de SESSION_COOKIE_AGE).

  • Debido a la forma en que funcionan las cookies, SESSION_EXPIRE_AT_BROWSER_CLOSE y SESSION_COOKIE_AGE son mutuamente excluyentes, es decir, la cookie caduca al cerrar el navegador o en el tiempo de caducidad especificado. Si se usa SESSION_COOKIE_AGE y el usuario cierra el navegador antes de que caduque, la cookie se conserva y la reapertura del navegador permitirá al usuario (o a cualquier otra persona) ingresar al sistema sin volver a autenticarse.

  • Django se basa solo en la cookie presente para determinar si la sesión está activa. No verifica la fecha de caducidad de la sesión almacenada con la sesión.

El siguiente método podría utilizarse para implementar este requisito y solucionar los problemas mencionados anteriormente.

  • No establezca SESSION_COOKIE_AGE.
  • Establezca la fecha de caducidad de la sesión como 'hora actual + período de inactividad' en cada solicitud.
  • Anula process_request en SessionMiddleware y comprueba la caducidad de la sesión. Deseche la sesión si ha expirado.

Requisito 3
cuando detectamos que la sesión ha expirado (en el SessionMiddleware personalizado a continuación), establecer un atributo de la solicitud para indicar la sesión de caducidad. Este atributo se puede usar para mostrar un mensaje apropiado al usuario.

Requisito 4
Uso de JavaScript para detectar inactividad del usuario, proporcionan la advertencia y también una opción para extender el período de sesiones. Si el usuario desea extender, envíe un pulso de mantener vivo al servidor para extender la sesión.

Requisito 5
Uso de JavaScript para detectar la actividad del usuario (durante la operación de negocio de largo) y enviar pulsos a mantener con vida al servidor para prevenir la sesión a expirar.


El enfoque de implementación anterior parece muy elaborado y me preguntaba si habría un método más simple (especialmente para Requisito 2).

Cualquier idea será muy apreciada.

+1

1 para proporcionar una solución detallada – Don

+1

"Debido a la forma en que funcionan las cookies, SESSION_EXPIRE_AT_BROWSER_CLOSE y SESSION_COOKIE_AGE son mutuamente excluyentes, es decir la cookie o bien expira el navegador cerca o en el momento de vencimiento determinado. Si se utiliza SESSION_COOKIE_AGE y el usuario cierra el navegador antes de que la cookie expire, la cookie se retiene y la reapertura del navegador permitirá al usuario (o a cualquier otra persona) ingresar al sistema sin volver a autenticarse ". Corrígeme si estoy equivocado, ¿pero esto ya no parece ser cierto en las versiones más nuevas de Django? (1.5+ al menos) –

+0

Hay un middleware que puede hacer lo que necesita. [en github] (https://github.com/subhranath/django-session-idle-timeout) y [en pypi] (http://pypi.python.org/pypi/django-session-idle-timeout/1.3 .1) – gbutler

Respuesta

38

Aquí hay una idea ... Vencimiento de la sesión en el navegador cerrar con la configuración SESSION_EXPIRE_AT_BROWSER_CLOSE. A continuación, establezca una marca de tiempo en la sesión en cada solicitud como tal.

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

y añada un middleware para detectar si la sesión ha caducado. algo como esto debe manejar todo el proceso ...

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 

A continuación, sólo tiene que hacer algunas URLs y vistas a devolver los datos correspondientes a las llamadas ajax respecto a la expiración de sesión.

cuando el usuario opta por "renovar" la sesión, por así decirlo, todo lo que tiene que hacer es configurar requeset.session['last_activity'] a la hora actual de nuevo

Obviamente este código es sólo un comienzo ... pero debe recibir que en el camino correcto

+0

Estoy siendo escéptico aquí, pero no creo que el 'if not request.is_ajax()' es completamente seguro. ¿No puede alguien que obtiene la boleta de pre-expiración de la sesión/enviar una llamada ajax y mantener la sesión en funcionamiento? –

+2

@ notbad.jpeg: en general, la "actividad" es fácilmente falsa.Alguien que se hace cargo de la sesión y sigue enviando solicitudes solo está activo. – RemcoGerlich

+0

Esta es una gran respuesta. El middleware es una herramienta muy poco utilizada en el desarrollo de Django. –

25

django-session-security hace precisamente eso ...

... con un requisito adicional: si el servidor no responde o un atacante desconecta la conexión a Internet: para su expiración de todos modos.

Disclamer: Mantengo esta aplicación. Pero he estado viendo este tema por un tiempo muy, muy largo tiempo :)

+1

aplicación genial, muy bien diseñado y bien construido. buen código limpio ... gracias. – nicorellius

+1

Actualizada regularmente también - gracias jpic – datakid

+0

Si el usuario cierra el navegador o la pestaña (sin cerrar la sesión) cuando se va, ¿todavía obliga al usuario a cerrar la sesión? ¿Maneja esta condición? – waterkinq

3

En la primera solicitud, se puede establecer la caducidad de sesión como

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

y cuando se utiliza el access_key y razón,

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

Votó por la ausencia de comentarios de downvoter. – Ruraj

9

Una manera fácil de satisfacer su segundo requisito sería establecer el valor de SESSION_COOKIE_AGE en la configuración.py a una cantidad adecuada de segundos. Por ejemplo:

SESSION_COOKIE_AGE = 600  #10 minutes. 

Sin embargo, sólo haciendo esto la sesión expirará al cabo de 10 minutos si es o no el usuario exhibe alguna actividad. Para hacer frente a este problema, el tiempo de expiración puede ser renovado automáticamente (durante otros 10 minutos adicionales) cada vez que el usuario realiza cualquier tipo de solicitud con la siguiente frase:

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

sólo soy bastante nuevo para usar Django.

Quería que la sesión expirara si el usuario registrado cerraba el navegador o si estaba inactivo (tiempo de inactividad) durante algún tiempo. Cuando busqué en Google para descubrirlo, esta pregunta SOF surgió primero. Gracias a una buena respuesta, busqué recursos para comprender cómo funciona middlewares durante el ciclo de solicitud/respuesta en Django. Fue muy útil.

Estaba a punto de aplicar middleware personalizado en mi código después de la respuesta superior aquí. Pero todavía estaba un poco sospechoso porque la mejor respuesta aquí fue editada en 2011. Me tomé más tiempo para buscar un poco de los resultados de búsqueda recientes y se me ocurrió de manera simple.

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

No he visto otros navegadores pero chrome. 1. Una sesión expiró cuando cerré un navegador incluso si SESSION_COOKIE_AGE configuró. 2. Solo cuando estaba inactivo durante más de 10 segundos, una sesión expiró. Gracias a SESSION_SAVE_EVERY_REQUEST, cada vez que se produce una nueva solicitud, se guarda la sesión y se agota el tiempo de espera de las actualizaciones

Para cambiar este comportamiento predeterminado, establezca SESSION_SAVE_EVERY_REQUEST en True. Cuando se establece en True, Django guardará la sesión en la base de datos en cada solicitud.

Tenga en cuenta que la cookie de sesión solo se envía cuando se ha creado o modificado una sesión. Si SESSION_SAVE_EVERY_REQUEST es True, la cookie de sesión se enviará en cada solicitud.

De forma similar, la parte de caducidad de una cookie de sesión se actualiza cada vez que se envía la cookie de sesión.

django manual 1.10

simplemente dejo respuesta por lo que algunas personas que es una especie de nuevo en Django como yo no paso mucho tiempo para averiguar la solución como una forma de haberlo hecho.

+0

¡Tú eres el hombre! Gracias por tu investigación. –

Cuestiones relacionadas