Django,如何获得cookie过期的时间

Django, how to get the time until a cookie expires

在标记为 dup 之前(我相信很多答案都是不正确的,因为): 根据我的研究:

settings.SESSION_SAVE_EVERY_REQUEST 在每次请求时刷新 cookie,这不是我想要实现的。

get_session_cookie_age() 只有 returns settings.SESSION_COOKIE_AGE 的值,如源代码所示:

def get_session_cookie_age(self):
    return settings.SESSION_COOKIE_AGE

我使用 cached_db 会话后端。缓存的部分none无效,因为它每次都必须保存cookie,因此SESSION_SAVE_EVERY_REQUEST不适用。我问这个问题的原因是因为我希望仅在剩余时间低于阈值时刷新 cookie,因此有些歇斯底里(具有缓存和自动刷新的好处)。

由于 get_expiry_age/get_expiry_date 的行为,我的代码无法正常工作,如上所述:

from django.conf import settings
from django.utils.deprecation import MiddlewareMixin

class SessionExpiry(MiddlewareMixin):
    def process_request(self, request):
        """Automatically refresh a session expirary at a certain limit.

        If request.session age goes below settings.SESSION_REFRESH, then
        set the sessions expirary age to settings.SESSION_COOKIE_AGE. The
        session is not refreshed every time to have the caching benefits of
        the cached_db backend.
        """
        try:
            empty = request.session.is_empty()
        except AttributeError:
            return None
        if (empty or not getattr(settings, 'SESSION_REFRESH', None)):
            return None
        if request.session.get_expiry_age() < settings.SESSION_REFRESH:
            request.session.set_expiry(settings.SESSION_COOKIE_AGE)
        return None

这是 Django 在设计和文档方面令人困惑的一个领域。弄清楚发生了什么的最简单方法是查看 source code.

要获得您想要的内容,您需要将自定义到期时间设置为 datetime。如果你使用秒(包括默认的SESSION_COOKIE_AGE)被解释为从现在开始的秒数;也就是说,无论何时你问。

因此要设置到期时间,请使用:

# Using timedelta will cause the session to save the expiration time as a datetime.
request.session.set_expiry(timedelta(seconds=settings.SESSION_COOKIE_AGE))

如果您这样做,对 get_expiry_age() 的调用将 return 当前日期时间与设置为到期日期时间之间的实际差异。

请务必注意 set_expiry() 文档中的警告:“请注意,只有在使用 PickleSerializer 时,datetimetimedelta 值才可序列化。”

从Django票子过来的。这是我想出的避免需要 pickle 序列化器和 SESSION_SAVE_EVERY_REQUEST 的方法。因此,我们可以使用纯时间戳而不是 datetime,并且由于 set_expire 不支持它,我们将添加另一个会话密钥来存储它。

class RefreshSessionMiddleware(middleware.SessionMiddleware):
    def process_response(self, request, response):
        session = request.session
        if not (session.is_empty() or session.get_expire_at_browser_close()):
            expiry = session.get('_session_expire_at_ts')
            now_ts = int(time.time())
            cookie_lifetime = session.get_expiry_age()
            if expiry is None or now_ts + cookie_lifetime / 2 > expiry:
                # This will set modified flag and update the cookie expiration time
                session['_session_expire_at_ts'] = now_ts + cookie_lifetime

        return super().process_response(request, response)