我有一个系统,每天24小时都有重叠的轮班工人。目前,一个人忘记退出并且下一个工作人员拿起他们的会话并使用它运行并不罕见。这会导致一些问责制问题。
我确实知道有会话长度的选项,即settings.SESSION_COOKIE_AGE
,但这些对我们的目的来说有点钝。我们有不同的工人,他们有不同的班次,管理人员有2FA的行动,而且基本上不是我们想要追求的道路。简单的说...
我想以编程方式设置登录时的会话死亡时间。
我们已经有了一个自定义的Login视图,但是这会通过内置的django.contrib.auth.forms.AuthenticationForm冒泡。即使在那里,我也看不到如何在特定会话上设置到期日。
有什么建议?
编辑:request.session
的.get_expiry_age()
和set_expiry(value)
似乎相关,但它们似乎确实更新,因为它们根据会话的最后修改时间而不是会话开始时循环。我需要一些能够在会话中设定最大年龄的东西。
编辑2:我想我可以在登录时写入会话并在外部运行一些东西(一个cronned管理whatsit)来检查expiries(如果存在)并且使每个会话失效。
得到了回答,感谢评论。登录时我将时间戳插入会话:
request.session['login_timestamp'] = timezone.now().timestamp()
如果你想知道为什么时间戳,而不是datetime.datetime.now()
或timezone.now()
,Django的默认会话编码器使用JSON,而Django的JSON编码器不处理日期时间。通过编写可以处理日期时间的编码器可以避免这种情况......但是只使用整数秒 - 自 - 纪元值对我来说已经足够了。
然后有一个小中间件来检查当前时间的会话。
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)
摧毁整个会议。如果您事先写了一条消息(存储在会话中),那么在logout(request)
之后它就会丢失。