首页 文章

如何在Django中因不活动而使会话失效?

提问于
浏览
78

我们的Django应用程序具有以下会话管理要求 .

当用户关闭浏览器时,

  • 会话将过期 .

  • 会话在一段时间不活动后过期 .

  • 检测会话何时因不活动而到期并向用户显示相应的消息 .

  • 在非活动期结束前几分钟警告即将到来的会话到期的用户 . 连同警告,为用户提供扩展会话的选项 .

  • 如果用户正在应用程序中处理不涉及发送到服务器的请求的长业务活动,则会话不得超时 .

在阅读了文档,Django代码和一些与此相关的博客文章后,我提出了以下实现方法 .

Requirement 1
通过将SESSION_EXPIRE_AT_BROWSER_CLOSE设置为True,可以轻松实现此要求 .

Requirement 2
我已经看到一些建议使用SESSION_COOKIE_AGE来设置会话到期时间 . 但是这种方法存在以下问题 .

  • 即使用户正在使用该应用程序,会话也始终在SESSION_COOKIE_AGE结束时到期 . (这可以通过使用自定义中间件在每个请求上将会话到期设置为SESSION_COOKIE_AGE来防止,或者通过将SESSION_SAVE_EVERY_REQUEST设置为true来保存每个请求的会话 . 但是由于使用了SESSION_COOKIE_AGE,下一个问题是不可避免的 . )

  • 由于cookie的工作方式,SESSION_EXPIRE_AT_BROWSER_CLOSE和SESSION_COOKIE_AGE是互斥的,即cookie在浏览器关闭或指定的到期时间到期 . 如果使用SESSION_COOKIE_AGE并且用户在cookie到期之前关闭浏览器,则会保留cookie并重新打开浏览器将允许用户(或任何其他人)进入系统而无需重新进行身份验证 .

  • Django仅依赖于存在的cookie来确定会话是否处于活动状态 . 它不会检查会话中存储的会话到期日期 .

可以使用以下方法来实现此要求并解决上述问题 .

  • 不要设置SESSION_COOKIE_AGE .

  • 在每个请求中将会话的到期日期设置为'current time + inactivity period' .

  • 覆盖SessionMiddleware中的process_request并检查会话是否到期 . 如果会话已过期,请将其丢弃 .

Requirement 3
当我们检测到会话已过期时(在上面的自定义SessionMiddleware中),在请求上设置一个属性以指示会话到期 . 此属性可用于向用户显示适当的消息 .

Requirement 4
使用JavaScript检测用户不活动,提供警告以及扩展会话的选项 . 如果用户希望扩展,则向服务器发送保持活动脉冲以扩展会话 .

Requirement 5
使用JavaScript检测用户活动(在长期业务操作期间)并向服务器发送保持活动脉冲以防止会话过期 .


上面的实现方法似乎很精细,我想知道是否有一个更简单的方法(特别是对于要求2) .

任何见解将受到高度赞赏 .

6 回答

  • 3

    满足第二个要求的一种简单方法是将settings.py中的SESSION_COOKIE_AGE值设置为适当的秒数 . 例如:

    SESSION_COOKIE_AGE = 600      #10 minutes.
    

    但是,仅通过这样做,会话将在10分钟后到期,无论用户是否展示某些活动 . 为了解决这个问题,每次用户使用以下句子执行任何类型的请求时,可以自动更新到期时间(另外10分钟):

    request.session.set_expiry(request.session.get_expiry_age())
    
  • 26

    你也可以使用stackoverflow build in functions

    SESSION_SAVE_EVERY_REQUEST = True
    
  • 3

    我只是很新用Django .

    如果记录的用户关闭浏览器或处于空闲(不活动超时)一段时间,我想使会话过期 . 当我用谷歌搜索它时,这个SOF问题首先出现了 . 感谢很好的回答,我查找了资源,以了解Django中请求/响应周期中的中间件如何工作 . 这非常有帮助 .

    我正准备将自定义中间件应用到我的代码中,然后在这里给出最佳答案 . 但我仍然有点怀疑,因为这里的最佳答案是在2011年编辑的 . 我花了更多的时间从最近的搜索结果中搜索一点,并提出了简单的方法 .

    SESSION_EXPIRE_AT_BROWSER_CLOSE = True
    SESSION_COOKIE_AGE = 10 # set just 10 seconds to test
    SESSION_SAVE_EVERY_REQUEST = True
    

    我没有检查其他浏览器,但铬 . 1.即使设置了SESSION_COOKIE_AGE,关闭浏览器时会话也会过期 . 2.只有当我闲置超过10秒时,A会话才会过期 . 感谢SESSION_SAVE_EVERY_REQUEST,每当您发出新请求时,它会保存会话并更新超时到期

    要更改此默认行为,请将SESSION_SAVE_EVERY_REQUEST设置为True . 设置为True时,Django会在每次请求时将会话保存到数据库 .

    请注意,会话cookie仅在创建或修改会话时发送 . 如果SESSION_SAVE_EVERY_REQUEST为True,则为每次请求都会发送会话cookie .

    同样,每次发送会话cookie时,会话cookie的到期部分都会更新 .

    django manual 1.10

    我只是留下答案,以便像我这样的Django中的一些新人不会花太多时间来找到解决方案 .

  • 40

    这是一个想法......使用 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置在浏览器关闭时使会话暂停 . 然后在每个请求上设置会话中的时间戳 .

    request.session['last_activity'] = datetime.now()
    

    并添加一个中间件来检测会话是否过期 . 这样的事情应该处理整个过程......

    from datetime import datetime
    from django.http import HttpResponseRedirect
    
    class SessionExpiredMiddleware:
        def process_request(request):
            last_activity = request.session['last_activity']
            now = datetime.now()
    
            if (now - last_activity).minutes > 10:
                # Do logout / expire session
                # and then...
                return HttpResponseRedirect("LOGIN_PAGE_URL")
    
            if not request.is_ajax():
                # don't set this for ajax requests or else your
                # expired session checks will keep the session from
                # expiring :)
                request.session['last_activity'] = now
    

    然后你只需要制作一些网址和视图,将相关数据返回到关于会话到期的ajax调用 .

    当用户选择"renew"会话时,可以这么说,你所要做的就是将 requeset.session['last_activity'] 再次设置为当前时间

    显然这段代码只是一个开始...但它应该让你走上正确的道路

  • 10

    在第一个请求中,您可以将会话到期时间设置为

    self.request.session['access_key'] = access_key
    self.request.session['access_token'] = access_token
    self.request.session.set_expiry(set_age) #in seconds
    

    当使用access_key和令牌时,

    try:
        key = self.request.session['access_key']
    except KeyError:
        age = self.request.session.get_expiry_age()
        if age > set_age:
            #redirect to login page
    
  • 21

    django-session-security就是那样......

    ...还有一项要求:如果服务器没有响应或者攻击者断开了互联网连接:它应该会过期 .

    免责声明:我维护这个应用程序 . 但是我一直在看这个帖子很长一段时间:)

相关问题