【问题标题】:Expiring a Django Session Regardless of Modified Time无论修改时间如何都使 Django 会话过期
【发布时间】:2016-10-26 14:19:36
【问题描述】:

来自Django's documentation for set_expiry

读取会话不被视为过期活动。会话过期时间从上次修改会话开始计算。

Django 的SESSION_COOKIE_AGE 设置默认值为1209600(2 周,以秒为单位)。因此,如果会话在 1 月 1 日午夜创建,它将设置为在 1 月 15 日午夜到期。但是,如果该会话在 1 月 14 日午夜被修改,那么它将被设置为 1 月 28 日午夜到期,而不是原来的 1 月 15 日午夜到期。

我对两周的默认生命周期很满意,但我想知道最有效的方法来确保所有会话始终在创建后两周内过期——即使它们被修改。似乎我必须编写一些中间件来检查会话创建时间,然后将过期时间设置为两周后,但似乎必须有比这更有效的方法。

【问题讨论】:

    标签: django session


    【解决方案1】:

    您应该扩展 django.contrib.session.backends.db.SessionBase 类并修改行为,因此只需快速查看该类,您就可以查看 save(...)get_expiry_date(...) 方法。

    这是一个自定义会话存储类的示例,如果具有该密钥的会话已存在,则不会更新会话的 expiry_date

    from django.contrib.sessions.backend.db import SessionStorage
    
    class MySessionStore(SessionStore):
        def save(self, must_create=False):
            """
            Saves the current session data to the database. If 'must_create' is
            True, a database error will be raised if the saving operation doesn't
            create a *new* entry (as opposed to possibly updating an existing
            entry).
            """
            if self.session_key is None:
                return self.create()
            existing_session = Session.objects.filter(session_key=self.session_key)
            expire_date = self.get_expiry_date()
            if existing_session.exists():
                #  Here we select the original expire_date from the database
                #  so when the session is modified and saved, expire_date
                #  remains unchanged
                if existing_session.first().expire_date is not None:
                    expire_date = existing_session.first().expire_date
            obj = Session(
                session_key=self._get_or_create_session_key(),
                session_data=self.encode(self._get_session(no_load=must_create)),
                expire_date=expire_date
            )
            using = router.db_for_write(Session, instance=obj)
            try:
                with transaction.atomic(using=using):
                    obj.save(force_insert=must_create, using=using)
            except IntegrityError:
                if must_create:
                    raise CreateError
                raise
    

    现在我们有一个自定义会话类,它不会在每次修改会话时更新到期日期,我们必须使用带有SESSION_ENGINE 设置的自定义会话类SESSION_ENGINE='path.to.MySessionStore'

    我没有测试过这个解决方案,我只是在回答一个问题:)

    【讨论】:

    • 啊,我应该考虑子类化!感谢您的建议!我很确定我只需要覆盖create 方法就可以了。它只需要两行!第一行:super(SessionStore, self).create() 第二行:self.set_expiry(timezone.now() + timedelta(seconds=settings.SESSION_COOKIE_AGE)) 我还没有对此进行彻底的测试,但从我所做的测试来看,它似乎有效。
    猜你喜欢
    • 2019-08-06
    • 2015-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 2012-02-29
    • 2021-08-18
    相关资源
    最近更新 更多