Django基于文件的会话不';过期

Django基于文件的会话不';过期,django,session,Django,Session,我刚刚意识到,当我使用基于文件的会话引擎时,我的会话不会过期。查看基于文件的会话的Django代码,Django不会存储会话的任何过期信息,因此除非手动删除会话文件,否则它永远不会过期 在我看来,这似乎是一个bug,因为数据库支持的会话工作得很好,我相信无论会话后端开发人员选择什么,它们的行为都应该类似 切换到数据库支持的会话对我来说不是一个选项,因为我需要将用户的会话存储在文件中 有人能发光吗? 这真的是一只虫子吗? 如果是,你建议我如何解决这个问题 谢谢 看来你是对的。至少在django 1

我刚刚意识到,当我使用基于文件的会话引擎时,我的会话不会过期。查看基于文件的会话的Django代码,Django不会存储会话的任何过期信息,因此除非手动删除会话文件,否则它永远不会过期

在我看来,这似乎是一个bug,因为数据库支持的会话工作得很好,我相信无论会话后端开发人员选择什么,它们的行为都应该类似

切换到数据库支持的会话对我来说不是一个选项,因为我需要将用户的会话存储在文件中

有人能发光吗? 这真的是一只虫子吗? 如果是,你建议我如何解决这个问题


谢谢

看来你是对的。至少在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
to
set\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
哦,好的,收到了。无论活动如何,我都希望使会话过期。谢谢你的快速回复。顺便说一句,您能否更新您的答案,以提及这一点(会话的实际目的是保存每个请求)?这可能对其他人有帮助。