¿Cómo determino cuándo un usuario tiene un tiempo de espera inactivo en Django?

StackOverflow https://stackoverflow.com/questions/644471

  •  22-07-2019
  •  | 
  •  

Pregunta

Me gustaría auditar cuando un usuario ha experimentado un tiempo de espera inactivo en mi aplicación Django. En otras palabras, si la fecha de vencimiento de la cookie de sesión del usuario excede la SESSION_COOKIE_AGE que se encuentra en settings.py, el usuario es redirigido a la página de inicio de sesión. Cuando eso ocurre, una auditoría también debe ocurrir. Por "auditoría", me refiero a que se debe escribir un registro en mi tabla person.audit.

Actualmente, he configurado un middleware para capturar estos eventos. Desafortunadamente, Django genera una nueva cookie cuando el usuario es redirigido a la página de inicio de sesión, por lo que no puedo determinar si el usuario fue llevado a la página de inicio de sesión a través de un tiempo de espera inactivo o algún otro evento.

Por lo que puedo decir, necesitaría trabajar con la " django_session " mesa. Sin embargo, los registros en esta tabla no pueden asociarse con ese usuario porque el valor de sessionid en la cookie se restablece cuando se produce la redirección.

Supongo que no soy el primero en encontrar este dilema. ¿Alguien tiene idea de cómo resolver el problema?

¿Fue útil?

Solución

Actualización:

Después de un poco de prueba, me doy cuenta de que el siguiente código no responde a su pregunta. Aunque funciona, y se llama al controlador de señal, prev_session_data si existe, no contendrá ninguna información útil.

Primero, un vistazo al marco de sesiones:

  1. Cuando un nuevo visitante solicita una URL de aplicación, se genera una nueva sesión para ellos; en este punto, todavía son anónimos ( request.user es una instancia de AnonymousUser).
  2. Si solicitan una vista que requiere autenticación, son redirigidos a la vista de inicio de sesión.
  3. Cuando se solicita la vista de inicio de sesión, establece un valor de prueba en la sesión del usuario ( SessionStore._session ); esto establece automáticamente los indicadores accedidos y modificado en la sesión actual.
  4. Durante la fase de respuesta de la solicitud anterior, el SessionMiddleware guarda la sesión actual, creando efectivamente una nueva instancia de Session en la tabla django_session (si está utilizando las sesiones predeterminadas respaldadas por la base de datos, proporcionadas por django.contrib.sessions.backends.db ). La identificación de la nueva sesión se guarda en la configuración de .SESSION_COOKIE_NAME .
  5. Cuando el usuario escribe su nombre de usuario y contraseña y envía el formulario, se autentica. Si la autenticación se realiza correctamente, se llama al método login de django.contrib.auth . login comprueba si la sesión actual contiene una ID de usuario; si lo hace, y la ID es la misma que la del usuario conectado, se llama a SessionStore.cycle_key para crear una nueva clave de sesión, mientras se conservan los datos de la sesión. De lo contrario, se llama a SessionStore.flush para eliminar todos los datos y generar una nueva sesión. Ambos métodos deben eliminar la sesión anterior (para el usuario anónimo) y llamar a SessionStore.create para crear una nueva sesión.
  6. En este punto, el usuario está autenticado y tiene una nueva sesión. Su ID se guarda en la sesión, junto con el backend utilizado para autenticarlos. El middleware de sesión guarda estos datos en la base de datos y guarda su nueva ID de sesión en la configuración de .SESSION_COOKIE_NAME .

Como puede ver, el gran problema con la solución anterior es cuando se llama a create (paso 5), la ID de la sesión anterior ya no existe. Como otros han señalado , esto sucede porque una vez que la cookie de sesión caduca, el navegador la elimina silenciosamente.

Basándose en Sugerencia de Alex Gaynor , Creo que se me ocurrió otro enfoque, que parece hacer lo que estás pidiendo, aunque todavía es un poco difícil. Básicamente, uso una segunda auditoría de larga duración. cookie, para reflejar la ID de sesión y algunos middleware para verificar la presencia de esa cookie. Para cualquier solicitud:

  • si no existen ni la cookie de auditoría ni la cookie de sesión, probablemente sea un nuevo usuario
  • si la cookie de auditoría existe, pero la cookie de sesión no, probablemente se trata de un usuario cuya sesión acaba de expirar
  • si existen ambas cookies y tienen el mismo valor, esta es una sesión activa

Aquí está el código hasta ahora:

sessionaudit.middleware.py :

from django.conf import settings
from django.db.models import signals
from django.utils.http import cookie_date
import time

session_expired = signals.Signal(providing_args=['previous_session_key'])

AUDIT_COOKIE_NAME = 'sessionaudit'

class SessionAuditMiddleware(object):
    def process_request(self, request):
        # The 'print' statements are helpful if you're using the development server
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
        audit_cookie = request.COOKIES.get(AUDIT_COOKIE_NAME, None)
        if audit_cookie is None and session_key is None:
            print "** Got new user **"
        elif audit_cookie and session_key is None:
            print "** User session expired, Session ID: %s **" % audit_cookie
            session_expired.send(self.__class__, previous_session_key=audit_cookie)
        elif audit_cookie == session_key:
            print "** User session active, Session ID: %s **" % audit_cookie

    def process_response(self, request, response):
        if request.session.session_key:
            audit_cookie = request.COOKIES.get(AUDIT_COOKIE_NAME, None)
            if audit_cookie != request.session.session_key:
                # New Session ID - update audit cookie:
                max_age = 60 * 60 * 24 * 365  # 1 year
                expires_time = time.time() + max_age
                expires = cookie_date(expires_time)
                response.set_cookie(
                    AUDIT_COOKIE_NAME,
                    request.session.session_key,
                    max_age=max_age,
                    expires=expires,
                    domain=settings.SESSION_COOKIE_DOMAIN,
                    path=settings.SESSION_COOKIE_PATH,
                    secure=settings.SESSION_COOKIE_SECURE or None
                )
        return response

audit.models.py :

from django.contrib.sessions.models import Session
from sessionaudit.middleware import session_expired

def audit_session_expire(sender, **kwargs):
    try:
        prev_session = Session.objects.get(session_key=kwargs['previous_session_key'])
        prev_session_data = prev_session.get_decoded()
        user_id = prev_session_data.get('_auth_user_id')
    except Session.DoesNotExist:
        pass

session_expired.connect(audit_session_expire)

settings.py :

MIDDLEWARE_CLASSES = (
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'sessionaudit.middleware.SessionAuditMiddleware',
    ...
)

INSTALLED_APPS = (
    ...
    'django.contrib.sessions',
    'audit',
    ...
)

Si está usando esto, debe implementar una vista de cierre de sesión personalizada, que elimine explícitamente la cookie de auditoría cuando el usuario cierre sesión. Además, sugeriría usar el middleware de cookies firmadas de django (pero probablemente ya lo esté haciendo, ¿no?)

ANTIGUO:

Creo que y

Otros consejos

SESSION_COOKIE_AGE = 1500 # 25 minutos

Ponga eso en su configuración y eso debería encargarse de eso y expirar la sesión.

No sé acerca de Django, pero ¿puede usted simplemente crear una cookie no persistente, que almacena el último tiempo de acceso a una página en su sitio (actualiza la cookie en cada carga de página)

Luego, en su página de inicio de sesión, puede verificar si su usuario tiene su cookie, pero no hay sesión, entonces, sabe que la sesión del usuario probablemente ha expirado. Dado que tiene el momento del último acceso a una página en su sitio, también puede calcular, en función de la duración de la sesión, si ha expirado el tiempo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top