【问题标题】:Is there a way to combine behavior of SESSION_EXPIRE_AT_BROWSER_CLOSE and SESSION_COOKIE_AGE有没有办法结合 SESSION_EXPIRE_AT_BROWSER_CLOSE 和 SESSION_COOKIE_AGE 的行为
【发布时间】:2012-03-05 07:03:09
【问题描述】:

出于安全原因,我将SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为true。

但是,浏览器长度的 cookie(一旦用户关闭他或她的浏览器即过期的 cookie)没有过期时间,那么SESSION_COOKIE_AGE 没有任何影响(是的,我检查过)。但我想在不活动时设置注销/超时,并在浏览关闭时注销。

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

【问题讨论】:

    标签: django session-timeout


    【解决方案1】:

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

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

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

    1. 创建一个新的custom middleware 来控制超时。
    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
    from django.contrib.auth import logout
    
    
    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 应用程序提供了一种机制来注销非活动的经过身份验证的用户。看看吧。

    【讨论】:

    • Empece a viajar y no quise volver ;) para como han dejado el pais politicos y banqueros...
    • 我在会话中存储 int(time.time()) - 自纪元以来的秒数。解决序列化问题
    • 嗨@Johan,你好心用int(time.time() )改进答案吗?
    猜你喜欢
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    • 2019-11-09
    • 2011-02-23
    • 2019-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多