【问题标题】:How to clear all session variables without getting logged out如何在不注销的情况下清除所有会话变量
【发布时间】:2013-04-08 23:55:43
【问题描述】:

我正在尝试清除所有会话变量,但不注销当前用户。

user = request.session.get('member_id', None)
request.session.flush()
request.session.modified = True
request.session['member_id'] = user
request.session.modified = True

这也会影响网站的其他用户吗?

【问题讨论】:

    标签: django python-2.7 django-sessions


    【解决方案1】:

    从 Django 1.8 开始,任何对 flush() 的调用都会注销用户。来自docs

    在 Django 1.8 中更改:删除会话 cookie 是一种行为 Django 1.8 中的新功能。以前,行为是重新生成 在 cookie 中发送回用户的会话键值。

    如果您希望能够删除密钥但让用户保持登录状态,则需要手动处理:

    for key in request.session.keys():
        del request.session[key]
    

    或者只是删除关注的特定键:

    del request.session['mykey']
    

    【讨论】:

    • 我收到一个错误:for key in request.session.keys(): RuntimeError: dictionary changed size during iteration。在下面修复。
    • @AdamG 将您的密钥收集到一个列表中,然后批量删除它们。当您正在迭代的可迭代对象发生变异时,这是非常典型的错误。
    • 替代方案:收集让用户在 dict 中保持登录所需的凭据 session.flush(),然后遍历该 dict 并将其放回会话中。
    【解决方案2】:

    在 django session.flush 删除会话数据并重新生成会话密钥。由于会话密钥是唯一的,因此不会影响其他用户。

    【讨论】:

    • 它只在 django 1.8 + 中?
    • 它至少从 1.3 开始就存在
    • 不明白为什么我在控制台中看不到 Session 对象的方法?我通过 Session.objects.get(session_key=...) 获取它
    • 因为这与 request.session 对象不同。如果您想在视图之外使用会话,请使用 docs.djangoproject.com/en/dev/topics/http/sessions/… 而不是 Session 模型。
    【解决方案3】:

    作为对 shacker's1 在 Python 2.x 中的改进,dict.keys() 返回一个字典键的列表副本,在 Python 3.x 中它改为返回一个迭代器。改变迭代器的大小是不明智的。对于版本安全的实现,强制转换到列表将防止任何大小问题

    for key in list(request.session.keys()):
        del request.session[key]
    

    我之前的回答建议使用dict.viewkeys(),但它也会在 python 3.x 中返回一个迭代器。

    【讨论】:

      【解决方案4】:

      您可以清除在 django 会话中设置的键,但要在不注销用户的情况下执行此操作需要一点技巧; request.session.flush() 将用户注销。而request.session = {} 在删除会话字典中的所有键时也会将用户注销。

      因此,要在不注销用户的情况下清除键,您必须避免以下划线字符开头的键。以下代码可以解决问题:

      for key in list(request.session.keys()):
        if not key.startswith("_"): # skip keys set by the django system
          del request.session[key]
      

      【讨论】:

        【解决方案5】:

        request.session 在内部使用 cookie。当用户请求网站的某个 url 时,只有该用户机器上的 cookie 才会发送到服务器。因此,request.session 始终与当前用户绑定。

        因此,这绝不会影响网站的其他用户。

        这也不会注销当前用户,因为您使用的是flush(),它将删除旧会话并创建一个新会话,并且这个新会话将与当前用户相关联。

        flush() 内部使用clear()delete()create()

        在响应中,新会话的密钥将作为 cookie 发送,在后续请求中,新会话将继续正常工作。

        【讨论】:

        • 那么为什么我在调用 request.session.flush() 时会被注销
        【解决方案6】:
        session_keys = list(request.session.keys())
            for key in session_keys:
                del request.session[key]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-08-03
          • 2012-06-04
          • 1970-01-01
          • 1970-01-01
          • 2017-02-10
          • 2015-03-03
          • 1970-01-01
          相关资源
          最近更新 更多