Django基于文件的会话不';过期
我刚刚意识到,当我使用基于文件的会话引擎时,我的会话不会过期。查看基于文件的会话的Django代码,Django不会存储会话的任何过期信息,因此除非手动删除会话文件,否则它永远不会过期 在我看来,这似乎是一个bug,因为数据库支持的会话工作得很好,我相信无论会话后端开发人员选择什么,它们的行为都应该类似 切换到数据库支持的会话对我来说不是一个选项,因为我需要将用户的会话存储在文件中 有人能发光吗? 这真的是一只虫子吗? 如果是,你建议我如何解决这个问题Django基于文件的会话不';过期,django,session,Django,Session,我刚刚意识到,当我使用基于文件的会话引擎时,我的会话不会过期。查看基于文件的会话的Django代码,Django不会存储会话的任何过期信息,因此除非手动删除会话文件,否则它永远不会过期 在我看来,这似乎是一个bug,因为数据库支持的会话工作得很好,我相信无论会话后端开发人员选择什么,它们的行为都应该类似 切换到数据库支持的会话对我来说不是一个选项,因为我需要将用户的会话存储在文件中 有人能发光吗? 这真的是一只虫子吗? 如果是,你建议我如何解决这个问题 谢谢 看来你是对的。至少在django 1
谢谢 看来你是对的。至少在django 1.4中,使用
django.contrib.sessions.backends.file
完全忽略SESSION\u COOKIE\u AGE
。我不确定这是否真的是一个bug,或者只是没有文档记录
如果您确实需要此功能,可以基于contrib中的文件后端创建自己的会话引擎,但可以使用过期功能对其进行扩展
打开django/contrib/sessions/backends/file.py并添加以下导入:
import datetime
from django.utils import timezone
然后,在load
方法中添加两行,如下所示:
def load(self):
session_data = {}
try:
session_file = open(self._key_to_file(), "rb")
if (timezone.now() - datetime.datetime.fromtimestamp(os.path.getmtime(self._key_to_file()))).total_seconds() > settings.SESSION_COOKIE_AGE:
raise IOError
try:
file_data = session_file.read()
# Don't fail if there is no data in the session file.
....
这实际上会比较会话文件上最后修改的日期,使其过期
将此文件保存到项目中的某个位置,并将其用作会话引擎,而不是'django.contrib.sessions.backends.file'
如果希望会话基于非活动状态超时,您还需要在设置中启用SESSION\u SAVE\u EVERY\u REQUEST
。一个选项是在存储会话的目录中使用tmpwatch
,我在Django 3.1
上遇到了类似问题。在我的例子中,我的程序在检查会话到期之前使用整数参数(int
数据类型)调用函数set\u expiry(value)
根据,参数value
toset\u expiry()
的数据类型可以是int
、datetime
或timedelta
。但是,对于基于文件的会话,只有在事先将int
参数传递给set\u expiry()
时,才能正常工作,并且set\u expiry()
的datetime
和timedelta
参数不会出现此类问题
简单的解决方案(解决方法?)是避免int
参数设置过期(值)
,您可以通过子类化django.contrib.sessions.backends.file.SessionStore
并重写设置过期(值)
(下面的代码示例)来实现,并在settings.py
from datetime import timedelta
from django.contrib.sessions.backends.file import SessionStore as FileSessionStore
class SessionStore(FileSessionStore):
def set_expiry(self, value):
""" force to convert to timedelta format """
if value and isinstance(value, int):
value = timedelta(seconds=value)
super().set_expiry(value=value)
注意:
将
timedelta
或datetime
传递到set\u expiration(value)
也可以,但您需要这样做。我喜欢这个想法,因为它易于实现。但是,它要求系统具有tmpwatch
。是的,我也在考虑将此路由作为最后手段。我可能应该询问Django用户或Django开发人员邮件列表,如果这确实是一个错误,为什么SESSION\u SAVE\u每个请求都需要启用?如果每次请求时都设置一个新的修改时间,这不是违背了会话过期的目的吗?如果没有session\u SAVE\u every\u request
,会话将在session\u COOKIE\u AGE
秒后过期,而不考虑活动。如果这正是您想要的,那么就不必费心于SESSION\u SAVE\u EVERY\u REQUEST
。如果您希望它只在SESSION\u COOKIE\u AGE
不活动几秒钟后过期,那么您希望SESSION\u SAVE\u每个请求
都是True
哦,好的,收到了。无论活动如何,我都希望使会话过期。谢谢你的快速回复。顺便说一句,您能否更新您的答案,以提及这一点(会话的实际目的是保存每个请求)?这可能对其他人有帮助。