有没有办法结合SESSION_EXPIRE_AT_BROWSER_CLOSE和SESSION_COOKIE_AGE的行为

dan*_*era 10 django session-timeout

出于安全考虑,我将SESSION_EXPIRE_AT_BROWSER_CLOSE设置为true.

但是,浏览器长度的cookie(一旦用户关闭他或她的浏览器就会过期的cookie)没有过期时间,那么SESSION_COOKIE_AGE没有效果(是的,我检查它).但我想在不活动时设置注销/超时加上注销浏览结束.

我的问题是,在浏览器长度的cookie场景中实现非活动超时/注销的最佳方法什么?

dan*_*era 19

正如您所解释的那样,SESSION_EXPIRE_AT_BROWSER_CLOSE和SESSION_COOKIE_AGE不兼容.当您为cookie设置过期日期时,此cookie不会成为浏览器长度的cookie.

然后,为了实现所需的行为,您应将SESSION_EXPIRE_AT_BROWSER_CLOSE设置为True并手动控制过期超时.

手动控制过期超时的优雅方式是:

  1. 创建一个控制超时的新自定义中间件.
  2. 修改settings.py以启用自定义中间件(和会话).

超时定制中间件可以是这样的:

# updated version that should work with django 1.10 middleware style
# tested up to django 2.2

import time
from django.conf import settings


class SessionIdleMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.user.is_authenticated:
            if 'last_request' in request.session:
                elapsed = time.time() - request.session['last_request']
                if elapsed > settings.SESSION_IDLE_TIMEOUT:
                    del request.session['last_request'] 
                    logout(request)
                    # flushing the complete session is an option as well!
                    # request.session.flush()  
            request.session['last_request'] = time.time()
        else:
            if 'last_request' in request.session:
                del request.session['last_request']

        response = self.get_response(request)

        return response
Run Code Online (Sandbox Code Playgroud)

请记住启用会话以便存储lastRequest.

这个解决方案是我编写和测试的,现在正在我的网站上工作.此代码具有GNU许可证;)

django 1.6的新功能(......两年后...)

如果您使用的是PickleSerializer,则日期时间和时间值只能序列化.如果没有,也许简单的解决方案是将datetime转换为unix时间戳并返回.可以在此翻译下方发布.

编辑

django-session-security app提供了一种注销非活动认证用户的机制.看一看.

  • 我在会话中存储int(time.time())-自纪元以来的秒数。解决序列化问题 (2认同)