Comment rechercher une session de django pour un utilisateur particulier?

J’écris une application où je vais accéder à la firebase database à partir de Django et à partir d’une application autonome. Les deux doivent faire une vérification de session et la session doit être la même pour les deux. Django a une authentification intégrée / une vérification de session, ce que j’utilise, maintenant je dois trouver comment réutiliser la même session pour mon application autonome.

Ma question est la suivante: comment puis-je rechercher une session_key pour un utilisateur particulier?

D’après ce qu’il semble, rien ne lie auth_user et django_session

La modification de la table django_session pour append un django_session explicite peut vous simplifier la vie. En supposant que vous fassiez cela (ou quelque chose de similaire), voici quatre approches pour mettre les choses à votre goût:

django.consortingb.session code django.consortingb.session . Je sais, je sais, c’est une chose horrible à suggérer. Mais ce ne sont que 500 lignes incluant tous les backends et moins les tests. C’est assez simple à pirater. C’est le meilleur itinéraire que si vous allez réorganiser sérieusement les choses.

Si vous ne voulez pas bifurquer, vous pouvez essayer de vous connecter au signal Session.post_save et vous y connecter.

Ou vous pourriez MonkeyPatch consortingb.session.models.Session.save() . Enveloppez simplement la méthode existante (ou créez-en une nouvelle), décomposez / synthétisez les valeurs dont vous avez besoin, stockez-les dans vos nouveaux champs, puis super(Session, self).save() .

Encore une autre façon de faire est de mettre 2 (oui, deux) classes de middleware – une avant et une après SessionMiddleware dans votre fichier settings.py . C’est à cause de la façon dont le middleware est traité. Celui répertorié après SessionMiddleware obtiendra, sur la demande entrante, une requête avec la session déjà attachée. La liste ci-dessus peut effectuer un traitement sur la réponse et / ou modifier / réenregistrer la session.

Nous avons utilisé une variante de cette dernière technique pour créer des pseudo-sessions pour les moteurs de recherche afin de leur donner un access spécial au matériel normalement réservé aux membres. Nous détectons également les liens entrants où le champ REFERER provient du moteur de recherche associé et nous accordons à l’utilisateur un access complet à cet article.

Mettre à jour:

Ma réponse est maintenant très ancienne, même si elle est toujours correcte. Voir la réponse beaucoup plus récente de @ Gavin_Ballard (29/09/2014) ci-dessous pour une autre approche de ce problème.

Cette réponse est postée cinq ans après la question initiale, mais cette tâche SO est l’un des meilleurs résultats de Google pour la recherche d’une solution à ce problème (et cela n’est toujours pas pris en charge avec Django).

J’ai une solution alternative pour le cas d’utilisation où vous êtes uniquement concerné par les sessions utilisateur connectées, qui utilisent un modèle UserSession supplémentaire pour UserSession utilisateurs à leurs sessions, par exemple:

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

Ensuite, vous pouvez simplement enregistrer une nouvelle instance UserSession chaque fois qu’un utilisateur se connecte:

 from django.consortingb.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) 

Et enfin, lorsque vous souhaitez répertorier (et éventuellement effacer) les sessions pour un utilisateur particulier:

 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() 

C’est ce que je veux dire, si vous souhaitez plus de détails, j’ai un article sur ce sujet.

C’est un peu difficile à faire, car toutes les sessions ne sont pas nécessairement associées à un utilisateur authentifié. L’infrastructure de session de Django prend également en charge les sessions anonymes, et toute personne visitant votre site disposera d’une session, qu’elle soit ou non connectée.

Ceci est rendu encore plus compliqué par le fait que l’object de session lui-même est sérialisé – Django n’ayant aucun moyen de savoir quelles données vous voulez stocker, il sérialise simplement le dictionnaire des données de session en une chaîne (en utilisant le “pickle” standard de Python). module) et l’insère dans votre firebase database.

Si vous avez la clé de session (qui sera envoyée par le navigateur de l’utilisateur en tant que valeur de cookie “sessionid”), la manière la plus simple d’obtenir les données consiste simplement à interroger la table Session pour cette session, qui renvoie une session. object. Vous pouvez ensuite appeler la méthode “get_decoded ()” de cet object pour obtenir le dictionnaire des données de session. Si vous n’utilisez pas Django, vous pouvez consulter le code source (django / consortingb / sessions / models.py) pour voir comment les données de session sont désérialisées.

Si vous avez l’ID utilisateur, cependant, vous devrez parcourir tous les objects Session, en désérialisant chacun et en en recherchant un qui a une clé nommée “_auth_user_id”, et pour laquelle la valeur de cette clé est l’ID utilisateur. .

J’ai trouvé cet extrait de code

 from django.consortingb.sessions.models import Session from django.consortingb.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 

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

Je n’ai pas encore vérifié, mais semble assez simple.

Peter Rowell, merci pour votre réponse. C’était une aide formidable. C’est ce que j’ai fait pour le faire fonctionner. Il suffit de changer un fichier dans djang.consortingb.sessions.

Dans django / consortingb / sessions / models.py, ajoutez le user_id à la table (ajoutez manuellement à la table de firebase database ou supprimez la table et exécutez 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) 

Maintenant, à votre avis, où vous vous connectez (si vous utilisez la connexion de base de Django, vous devrez la remplacer)

 # 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() 

Cela a fonctionné pour moi.

J’ai rencontré ce problème lorsque j’ai voulu expulser un spammeur. Il semble que mettre leur compte à “inactif” ne suffit pas, car ils peuvent toujours entrer dans leur session précédente. Alors, comment supprimer une session pour un utilisateur spécifique ou comment expirer délibérément une session pour un utilisateur spécifique?

La solution consiste à utiliser le champ last_login pour rechercher l’heure à laquelle la session a été désactivée, ce qui vous indique que la date d’ expire_date est deux semaines plus tard, ce qui vous permet d’effectuer un filtre utile sur la table des sessions:

 from django.consortingb.sessions.models import Session from django.consortingb.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()