with vincent page custom and django authentication session

vincent - login url django



¿Cómo buscar la sesión django para un usuario en particular? (6)

Encontré este fragmento de código

from django.contrib.sessions.models import Session from django.contrib.auth.models import User session_key = ''8cae76c505f15432b48c8292a7dd0e54'' session = Session.objects.get(session_key=session_key) uid = session.get_decoded().get(''_auth_user_id'') user = User.objects.get(pk=uid) print user.username, user.get_full_name(), user.email

aquí http://scottbarnham.com/blog/2008/12/04/get-user-from-session-key-in-django/

Aún no lo he verificado, pero parece bastante sencillo.

Estoy escribiendo una aplicación en la que accederé a la base de datos desde django y desde una aplicación independiente. Ambos necesitan hacer la verificación de la sesión y la sesión debería ser la misma para ambos. Django tiene una autentificación / verificación de sesión incorporada, que es lo que estoy usando, ahora necesito descubrir cómo reutilizar la misma sesión para mi aplicación independiente.

Mi pregunta es ¿cómo puedo buscar una session_key para un usuario en particular?

Por lo que parece, no hay nada que vincule auth_user y django_session


Esta respuesta se publica cinco años después de la pregunta original, pero este hilo SO es uno de los principales resultados de Google cuando se busca una solución a este problema (y sigue siendo algo que no se admite de manera inmediata con Django).

Tengo una solución alternativa para el caso de uso en la que solo te preocupan las sesiones de usuario registradas, que usan un modelo de UserSession adicional para asignar usuarios a sus sesiones, algo como esto:

from django.conf import settings from django.db import models from django.contrib.sessions.models import Session class UserSession(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL) session = models.ForeignKey(Session)

Luego, puede simplemente guardar una nueva instancia de UserSession cada vez que un usuario UserSession sesión:

from django.contrib.auth.signals import user_logged_in def user_logged_in_handler(sender, request, user, **kwargs): UserSession.objects.get_or_create(user = user, session_id = request.session.session_key) user_logged_in.connect(user_logged_in_handler)

Y finalmente, cuando desee listar (y posiblemente borrar) las sesiones para un usuario en particular:

from .models import UserSession def delete_user_sessions(user): user_sessions = UserSession.objects.filter(user = user) for user_session in user_sessions: user_session.session.delete()

Esa es la base, si desea más detalles, tengo una publicación de blog que lo cubre.


Esto es algo complicado de hacer, porque no todas las sesiones están necesariamente asociadas a un usuario autenticado; El marco de sesiones de Django también admite sesiones anónimas, y cualquiera que visite su sitio tendrá una sesión, independientemente de si están o no registradas.

Esto se complica aún más por el hecho de que el objeto de sesión en sí mismo está serializado, ya que Django no tiene manera de saber qué datos exactamente desea almacenar, simplemente serializa el diccionario de datos de sesión en una cadena (usando el "pickle" estándar de Python) módulo) y lo incluye en su base de datos.

Si tiene la clave de sesión (que será enviada por el navegador del usuario como el valor de la cookie "sessionid"), la forma más fácil de acceder a los datos es simplemente consultar la tabla de sesión para la sesión con esa clave, que devuelve una sesión objeto. A continuación, puede llamar al método "get_decoded ()" de ese objeto para obtener el diccionario de datos de la sesión. Si no está utilizando Django, puede consultar el código fuente (django / contrib / sessions / models.py) para ver cómo se deserializan los datos de la sesión.

Sin embargo, si tiene la identificación de usuario, deberá recorrer todos los objetos de sesión, deserializar cada uno y buscar uno que tenga una clave llamada "_auth_user_id", y cuyo valor de esa clave sea la identificación del usuario. .


Me encontré con este problema cuando quería expulsar a un spammer. Parece que establecer su cuenta en "inactivo" no es suficiente, porque aún pueden aparecer en su sesión anterior. Entonces, ¿cómo eliminar una sesión para un usuario específico o cómo expirar deliberadamente una sesión para un usuario específico?

La respuesta es last_login campo last_login para rastrear la hora en que se deshabilitó la sesión, lo que le indica que expire_date es dos semanas después, lo que le permite realizar un filtro útil en la tabla de sesiones:

from django.contrib.sessions.models import Session from django.contrib.auth.models import User from datetime import datetime from dateutil.relativedelta import relativedelta baduser = User.objects.get(username="whoever") two_weeks = relativedelta(weeks=2) two_hours = relativedelta(hours=2) expiry = baduser.last_login + two_weeks sessions = Session.objects.filter( expire_date__gt=expiry - two_hours, expire_date__lt=expiry + two_hours ) print sessions.count() # hopefully a manageable number for s in sessions: if s.get_decoded().get(''_auth_user_id'') == baduser.id: print(s) s.delete()


Peter Rowell, gracias por tu respuesta. Fue una gran ayuda. Esto es lo que hice para que funcione. Solo tuvo que cambiar un archivo en djang.contrib.sessions.

En django / contrib / sessions / models.py, agregue user_id a la tabla (agregue manualmente a la tabla DB o elimine la tabla y ejecute manage.py syncdb).

class Session(models.Model): ... user_id = models.IntegerField(_(''user_id''), null=True) ... def save(self, *args, **kwargs): user_id = self.get_decoded().get(''_auth_user_id'') if ( user_id != None ): self.user_id = user_id # Call the "real" save() method. super(Session, self).save(*args, **kwargs)

Ahora, desde su punto de vista, donde inicia sesión (si utiliza el inicio de sesión base de django, deberá anularlo)

# On login, destroy all prev sessions # This disallows multiple logins from different browsers dbSessions = Session.objects.filter( user_id = request.user.id ) for index, dbSession in enumerate( dbSessions ): if ( dbSession.session_key != request.session.session_key ): dbSession.delete()

Esto funcionó para mí.


La modificación de la tabla django_session para agregar un user_id explícito puede hacer la vida mucho más fácil. Asumiendo que hagas eso (o algo similar), aquí hay cuatro enfoques para abatir las cosas a tu gusto:

Tenedor el código django.contrib.session . Lo sé, lo sé, es algo horrible de sugerir. Pero solo son 500 líneas, incluidos todos los back-end y menos las pruebas. Es bastante fácil de hackear. Esta es la mejor ruta solo si vas a hacer una reorganización seria de las cosas.

Si no desea bifurcar, puede intentar conectarse a la señal de Session.post_save y pasar allí.

O podría MonkeyPatch contrib.session.models.Session.save() . Simplemente ajuste el método existente (o cree uno nuevo), desglose / sintetice los valores que necesite, almacénelos en sus nuevos campos, y luego super(Session, self).save() .

Otra forma de hacerlo es colocar 2 (sí, dos) clases de middleware, una antes y después de SessionMiddleware en su archivo settings.py . Esto se debe a la forma en que se procesa el middleware. El que aparece después de SessionMiddleware obtendrá, en la solicitud de entrada, una solicitud con la sesión ya asociada. El que se mencionó anteriormente puede hacer cualquier procesamiento en la respuesta y / o cambiar / volver a guardar la sesión.

Utilizamos una variación de esta última técnica para crear pseudo-sesiones para las arañas de los motores de búsqueda para darles acceso especial al material que normalmente es solo para miembros. También detectamos enlaces entrantes en los que el campo REFERER pertenece al motor de búsqueda asociado y le damos acceso total al usuario a ese artículo.

Actualizar:

Mi respuesta ahora es bastante antigua, aunque sigue siendo en su mayoría correcta. Vea la respuesta mucho más reciente de @Gavin_Ballard (9/29/2014) a continuación para otro acercamiento a este problema.