代码之家  ›  专栏  ›  技术社区  ›  Oli

在登录时在特定时间为特定用户终止django会话(例如当其轮班结束时)

  •  0
  • Oli  · 技术社区  · 7 年前

    我有一个全天候轮班的系统。目前,一个人忘记注销而下一个工作人员拿起他们的会话并与其一起运行的情况并不少见。这导致了一些责任问题。

    我真的意识到有很多选择 settings.SESSION_COOKIE_AGE 但就我们的目的而言,这些都有点生硬。我们有不同的员工和不同的轮班时间,经理们有2FA的行动,这基本上不是我们想要追求的道路。简单地说…

    我想在登录时以编程方式设置会话结束时间。

    我们已经有了一个自定义的登录视图,但是这会通过内置的django.contrib.auth.forms.authenticationform弹出。即使在那里,我也看不到如何设置特定会话的过期时间。

    有什么建议吗?

    编辑 : request.session .get_expiry_age() set_expiry(value) 似乎相关 但是 它们之所以会更新,是因为它们会根据上次修改会话的时间而不是会话启动的时间循环。我需要一个能设定疗程最大年龄的东西。

    编辑2 :我想我可以写 进入之内 登录时的会话并在外部运行某个程序(cronned management whatsit),该程序检查过期时间(如果存在)并对每个失效的会话进行nuck操作。

    0 回复  |  直到 7 年前
        1
  •  1
  •   Oli    7 年前

    由于这些评论,我想出了一个答案。登录时,我将时间戳插入会话:

    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) 破坏整个会话。如果您事先写了一条消息(存储在会话中),它将在 注销(请求) .