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

时间:2012-02-13 21:02:12

标签: django session-timeout

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

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

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

1 个答案:

答案 0 :(得分:18)

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

然后,为了达到您想要的行为,您应该将SESSION_EXPIRE_AT_BROWSER_CLOSE设置为True并控制手动过期超时

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

  1. 创建一个控制超时的新custom middleware
  2. 修改settings.py以启用自定义中间件(和会话)。
  3. 超时自定义中间件可能如下所示:

    # 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
    

    古代Django版本的解决方案(1.10之前版本)

    class timeOutMiddleware(object):
    
        def process_request(self, request):
            if request.user.is_authenticated():
                if 'lastRequest' in request.session:            
                    elapsedTime = datetime.datetime.now() - \
                                  request.session['lastRequest']
                    if elapsedTime.seconds > 15*60:
                        del request.session['lastRequest'] 
                        logout(request)
    
                request.session['lastRequest'] = datetime.datetime.now()
            else:
                if 'lastRequest' in request.session:
                    del request.session['lastRequest'] 
    
            return None
    

    请务必启用sessions以存储lastRequest

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

    关于django 1.6的新内容(......两年后......)

    如果您使用PickleSerializer,则日期时间和时间范围值仅可序列化。如果没有,也许简单的解决方案是translate datetime to unix timestamp and back。可以在此翻译下方发布。

    <强>被修改

    django-session-security app提供了一种注销非活动身份验证用户的机制。看一看。