登录时,特定用户(例如,当轮班结束时)在特定时间到期Django会话

时间:2019-04-16 12:28:02

标签: django session django-authentication django-sessions

我有一个24/7全天候工作人员重叠的系统。当前,忘记退出并由下一个工作人员接听并运行会话的情况并不少见。这会导致一些问责制问题。

我确实知道会话长度有一些选择,例如settings.SESSION_COOKIE_AGE,但是对于我们的目的来说这些有点钝了。我们有不同轮班时间的工人,负责2FA运作的经理,这基本上不是我们想要追求的道路。简单地说...

我想以编程方式设置登录时的会话终止时间。

我们已经有一个自定义的Login视图,但这通过内置的django.contrib.auth.forms.AuthenticationForm冒泡了。甚至在那里,我也看不到如何为特定会话设置到期时间。

有什么建议吗?

编辑request.session的{​​{1}}和.get_expiry_age()似乎相关,但是的确会更新,因为它们会根据关于会话的最后修改时间,而不是会话开始时间。我需要设置会话的最大年龄的东西。

编辑2 :我想我可以在登录时将写入会话,并在外部运行某些东西(管理问题),以检查到期时间(如果存在)并进行核操作每次会话失败。

1 个答案:

答案 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)之后将丢失该消息。