【发布时间】:2012-03-05 07:03:09
【问题描述】:
出于安全原因,我将SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为true。
但是,浏览器长度的 cookie(一旦用户关闭他或她的浏览器即过期的 cookie)没有过期时间,那么SESSION_COOKIE_AGE 没有任何影响(是的,我检查过)。但我想在不活动时设置注销/超时,并在浏览关闭时注销。
我的问题是,在浏览器长度的 cookie 场景中实现不活动超时/注销的最佳方法是什么?
【问题讨论】:
出于安全原因,我将SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为true。
但是,浏览器长度的 cookie(一旦用户关闭他或她的浏览器即过期的 cookie)没有过期时间,那么SESSION_COOKIE_AGE 没有任何影响(是的,我检查过)。但我想在不活动时设置注销/超时,并在浏览关闭时注销。
我的问题是,在浏览器长度的 cookie 场景中实现不活动超时/注销的最佳方法是什么?
【问题讨论】:
正如您所解释的,SESSION_EXPIRE_AT_BROWSER_CLOSE 和 SESSION_COOKIE_AGE 不兼容。当您为 cookie 设置过期日期时,该 cookie 将变为无浏览器长度的 cookie。
为了实现您想要的行为,您应该将 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 True 并手动控制过期超时。
手动控制过期超时的优雅方法是:
超时自定义中间件可以如下所示:
# 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 应用程序提供了一种机制来注销非活动的经过身份验证的用户。看看吧。
【讨论】:
int(time.time() )改进答案吗?