我有一个24/7全天候工作人员重叠的系统。当前,忘记退出并由下一个工作人员接听并运行会话的情况并不少见。这会导致一些问责制问题。
我确实知道会话长度有一些选择,例如settings.SESSION_COOKIE_AGE
,但是对于我们的目的来说这些有点钝了。我们有不同轮班时间的工人,负责2FA运作的经理,这基本上不是我们想要追求的道路。简单地说...
我想以编程方式设置登录时的会话终止时间。
我们已经有一个自定义的Login视图,但这通过内置的django.contrib.auth.forms.AuthenticationForm冒泡了。甚至在那里,我也看不到如何为特定会话设置到期时间。
有什么建议吗?
编辑:request.session
的{{1}}和.get_expiry_age()
似乎相关,但是的确会更新,因为它们会根据关于会话的最后修改时间,而不是会话开始时间。我需要设置会话的最大年龄的东西。
编辑2 :我想我可以在登录时将写入会话,并在外部运行某些东西(管理问题),以检查到期时间(如果存在)并进行核操作每次会话失败。
答案 0 :(得分:1)
感谢评论,提出答案。登录时,我将时间戳记插入会话:
request.session['login_timestamp'] = timezone.now().timestamp()
如果您想知道为什么使用时间戳而不是datetime.datetime.now()
或timezone.now()
,则Django的默认会话编码器使用JSON,而Django的JSON编码器不处理日期时间。通过编写可以处理日期时间的编码器可以避免这种情况。但是,仅使用整数seconds-since-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)
破坏了整个会话。如果您事先写了一条消息(存储在会话中),则在logout(request)
之后将丢失该消息。