如何在不注销的情况下清除所有会话变量
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]
【讨论】:
以上是关于如何在不注销的情况下清除所有会话变量的主要内容,如果未能解决你的问题,请参考以下文章