当前位置:  开发笔记 > 编程语言 > 正文

如何为特定用户查找django会话?

如何解决《如何为特定用户查找django会话?》经验,为你挑选了6个好方法。

我正在编写一个应用程序,我将从django和独立应用程序访问数据库.两者都需要进行会话验证,并且两者的会话应该相同.Django有一个内置的身份验证/会话验证,这就是我正在使用的,现在我需要弄清楚如何为我的独立应用程序重用相同的会话.

我的问题是如何查找特定用户的session_key?

从它的外观来看,没有任何东西将auth_user和django_session联系在一起



1> Gavin Ballar..:

这个答案是在原始问题发布五年之后发布的,但是这个SO线程是搜索此问题的解决方案时谷歌的最佳结果之一(并且它仍然是Django不支持的东西).

我有一个用例的备用解决方案,你只关心登录的用户会话,它使用一个额外的UserSession模型将用户映射到他们的会话,如下所示:

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)  

然后,您可以UserSession在用户登录时随时保存新实例:

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)

最后,当您想列出(并可能清除)特定用户的会话时:

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

这就是它的基本要点,如果你想了解更多细节,我会有一篇博文来介绍它.


我遇到的问题是当`user_logged_in`触发时,会话不一定被保存,因此得到FK约束错误.首先在`user_logged_in_handler()`中运行`request.session.save()`是否安全?或者,我可以将FK字段更改为文本,但这意味着我可能需要进行一些额外的清理.

2> James Bennet..:

这有点棘手,因为并非每个会话都必须与经过身份验证的用户相关联; Django的会话框架也支持匿名会话,访问您网站的任何人都会有一个会话,无论他们是否已登录.

会话对象本身被序列化的事实使得这变得更加棘手 - 因为Django无法知道您想要存储哪些数据,它只是将会话数据字典序列化为字符串(使用Python的标准"pickle")模块)和填充到数据库中的东西.

如果你有会话密钥(将由用户的浏览器作为cookie值"sessionid"发送),获取数据的最简单方法就是在Session表中查询具有该密钥的会话,该密钥返回一个Session宾语.然后,您可以调用该对象的"get_decoded()"方法来获取会话数据的字典.如果您不使用Django,可以查看源代码(django/contrib/sessions/models.py)以查看会话数据的反序列化方式.

但是,如果您具有用户标识,则需要循环遍历所有Session对象,对每个对象进行反序列化并查找具有名为"_auth_user_id"的密钥的对象,并且该密钥的值为用户标识.



3> michael..:

我找到了这段代码

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

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

尚未验证,但看起来很直接.


直截了当,但反向操作.从用户id获取密钥(不修改模型)需要迭代每个会话.

4> Peter Rowell..:

修改django_session表以添加显式user_id可以使生活更轻松.假设你这样做(或类似的东西),这里有四种方法可以根据自己的喜好调整事物:

分叉django.contrib.session代码.我知道,我知道,这是一个可怕的建议.但它只有500行,包括所有后端和减去测试.破解非常简单.只有当你要做一些严肃的重新安排时,这才是最好的路线.

如果您不想分叉,可以尝试连接Session.post_save信号并在那里进行扫描.

或者你可以使用MonkeyPatch contrib.session.models.Session.save().只需包装现有方法(或创建一个新方法),分解/合成您需要的任何值,然后将它们存储在新字段中super(Session, self).save().

另一种方法是SessionMiddleware在你的settings.py文件中放入2个(是的,两个)中间件类 - 一个在之前和之后一个.这是因为中间件的处理方式.之后列出的那个SessionMiddleware将在入站请求中获得已附加会话的请求.之前列出的那个可以对响应进行任何处理和/或更改/重新保存会话.

我们使用最后一种技术的变体来为搜索引擎蜘蛛创建伪会话,以便为他们提供对通常仅限成员的材料的特殊访问.我们还检测REFERER字段来自关联搜索引擎的入站链接,并且我们为用户提供对该文章的完全访问权限.

更新:

我的答案现在相当古老,尽管它仍然是正确的.有关此问题的另一种方法,请参阅下面的@ Gavin_Ballard最近的答案(2014年9月29日).


Django用户会话现在可用于提供此功能:https://github.com/Bouke/django-user-sessions

5> 小智..:

彼得罗威尔,谢谢你的回应.这是一个巨大的帮助.这就是我为了让它发挥作用所做的.只需要在djang.contrib.sessions中更改一个文件.

在django/contrib/sessions/models.py中,将user_id添加到表中(手动添加到DB表或删除表并运行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)

现在在您查看登录的位置(如果使用django的基本登录,则必须覆盖它)

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

这对我有用.



6> hwjp..:

当我想要发垃圾邮件时,我遇到了这个问题.似乎将他们的帐户设置为"不活动"是不够的,因为他们仍然可以进入他们之前的会话.那么 - 如何删除特定用户的会话,或者如何故意使特定用户的会话失效?

答案是使用该last_login字段来跟踪会话被禁用的时间,这会告诉您expire_date两周之后,这会让您在会话表上执行有用的过滤器:

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

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有