由于这些评论,我想出了一个答案。登录时,我将时间戳插入会话:
request.session['login_timestamp'] = timezone.now().timestamp()
如果你想知道为什么时间戳,而不是
datetime.datetime.now()
或
timezone.now()
,django的默认会话编码器使用json,django的json编码器不处理日期时间。这是通过编写一个可以处理日期时间的编码器来避免的…但仅仅用一个整数秒,因为epoch值对我来说已经足够了。
然后有一个小的中间件来对照当前时间检查会话。
from django.contrib.auth import logout
class MyMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# other checks to make sure this middleware should run.
# eg, this only happens on authenticated URLs
login_timestamp_ago = timezone.now().timestamp() - request.session.get('login_timestamp', timezone.now().timestamp())
if settings.RECEPTION_LOGIN_DURATION and <insert user checks here> and login_timestamp_ago >= settings.RECEPTION_LOGIN_DURATION:
logout(request) # nukes session
messages.warning(request, "Your session has expired. We need you to log in again to confirm your identity.")
return redirect(request.get_full_path())
这里的事件顺序很重要。
logout(request)
破坏整个会话。如果您事先写了一条消息(存储在会话中),它将在
注销(请求)
.