如何在不注销的情况下清除所有会话变量

Posted

技术标签:

【中文标题】如何在不注销的情况下清除所有会话变量【英文标题】: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

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

【问题讨论】:

【参考方案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]

【讨论】:

以上是关于如何在不注销的情况下清除所有会话变量的主要内容,如果未能解决你的问题,请参考以下文章

如何清除所有会话变量而不退出

用户在 ASP .NET MVC 5 中注销时如何清除所有会话元素?

浏览历史记录清除网页后注销[重复]

如何在不单击任何按钮的情况下将复选框值放入会话变量中?

如何在不退出的情况下更新会话值?

如果用户忘记注销并关闭浏览器,如何删除 Rails 中以前的会话?