Python 由于Django中的不活动,如何使会话过期?

Python 由于Django中的不活动,如何使会话过期?,python,django,session,cookies,Python,Django,Session,Cookies,我们的Django应用程序具有以下会话管理需求 会话在用户关闭浏览器时过期 会话在一段时间不活动后过期 检测会话何时因不活动而过期,并向用户显示相应的消息 在非活动期结束前几分钟警告用户会话即将到期。除了警告之外,还为用户提供了一个扩展会话的选项 如果用户正在应用程序中处理一个不涉及向服务器发送请求的长时间业务活动,则会话不得超时 在阅读了文档、Django代码和一些与此相关的博客文章之后,我提出了以下实现方法 要求1 通过将浏览器上的会话设置为接近True,可以轻松实现此要求 要求2 我看到了

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

  • 会话在用户关闭浏览器时过期
  • 会话在一段时间不活动后过期
  • 检测会话何时因不活动而过期,并向用户显示相应的消息
  • 在非活动期结束前几分钟警告用户会话即将到期。除了警告之外,还为用户提供了一个扩展会话的选项
  • 如果用户正在应用程序中处理一个不涉及向服务器发送请求的长时间业务活动,则会话不得超时
  • 在阅读了文档、Django代码和一些与此相关的博客文章之后,我提出了以下实现方法

    要求1
    通过将浏览器上的会话设置为接近True,可以轻松实现此要求

    要求2
    我看到了一些建议,建议使用SESSION\u COOKIE\u AGE来设置会话到期时间。但这种方法存在以下问题

    • 即使用户正在积极使用应用程序,会话始终在会话\u COOKIE \u期结束时过期。(可以通过使用自定义中间件将每个请求的会话到期时间设置为session\u COOKIE\u AGE,或者通过将session\u SAVE\u every\u request设置为true来保存每个请求的会话来防止这种情况。但是由于使用session\u COOKIE\u AGE,下一个问题是不可避免的。)


    • 由于COOKIE的工作方式,会话在浏览器关闭时过期和会话COOKIE过期是相互排斥的,即COOKIE在浏览器关闭时过期或在指定的过期时间过期。如果使用了会话\u COOKIE\u AGE,并且用户在COOKIE过期之前关闭浏览器,则会保留COOKIE,重新打开浏览器将允许用户(或任何其他人)进入系统,而无需重新验证


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

    以下方法可用于实现此需求并解决上述问题

    • 不要设置会话\u COOKIE\u年龄
    • 在每次请求时,将会话的到期日期设置为“当前时间+非活动期”
    • 覆盖SessionMiddleware中的进程请求并检查会话是否过期。如果会话已过期,则放弃该会话
    要求3
    当我们检测到会话已过期时(在上面的自定义SessionMiddleware中),在请求上设置一个属性以指示会话过期。此属性可用于向用户显示适当的消息

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

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


    上面的实现方法看起来非常复杂,我想知道是否有更简单的方法(特别是对于需求2)


    任何见解都将受到高度赞赏。

    这里有一个想法。。。使用
    session\u Expire\u AT\u browser\u 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
    
    然后,您只需要创建一些URL和视图,将有关会话到期的相关数据返回给ajax调用

    当用户选择“续订”会话时,您所要做的就是将
    requeset.session['last_activity']]
    再次设置为当前时间

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

    正是这样做的

    。。。还有一个额外的要求:如果服务器没有响应或者攻击者断开了internet连接,那么它无论如何都应该过期

    Disclamer:我维护这个应用程序。但是我已经看了这个帖子很长很长时间了:)

    你也可以用


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

    self.request.session['access_key'] = access_key
    self.request.session['access_token'] = access_token
    self.request.session.set_expiry(set_age) #in seconds 
    
    当使用访问密钥和令牌时

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

    满足第二个要求的一个简单方法是将settings.py中的SESSION\u COOKIE\u AGE值设置为合适的秒数。例如:

    SESSION_COOKIE_AGE = 600      #10 minutes.
    
    但是,只要这样做,会话将在10分钟后过期,无论用户是否表现出某些活动。为了解决此问题,每次用户执行以下语句的任何请求时,都可以自动延长到期时间(再延长10分钟):

    request.session.set_expiry(request.session.get_expiry_age())
    

    我刚刚开始使用Django

    如果登录用户关闭浏览器或处于空闲状态(不活动超时)一段时间,我想使会话过期。当我用谷歌搜索出来的时候,这个问题首先出现了。由于回答得很好,我查阅了参考资料,以了解Django中的中间件在请求/响应周期中是如何工作的。这很有帮助

    我正准备在我的代码中应用自定义中间件,下面是最重要的答案。但我还是有点怀疑,因为这里的最佳答案是在2011年编辑的。我花了更多的时间从最近的搜索结果中搜索一点点,并想出了一个简单的方法

    SESSION_EXPIRE_AT_BROWSER_CLOSE = True
    SESSION_COOKIE_AGE = 10 # set just 10 seconds to test
    SESSION_SAVE_EVERY_REQUEST = True
    
    除了chrome,我没有检查其他浏览器。 1.即使设置了会话\u COOKIE\u年龄,当我关闭浏览器时会话也已过期。 2.只有当我空闲超过10秒时,会话才过期。由于SESSION_SAVE_EVERY_请求,每当出现新请求时,它都会保存会话并更新超时以使其过期

    要更改此默认值
    SESSION_EXPIRE_AT_BROWSER_CLOSE = True
    SESSION_COOKIE_AGE = 10 # set just 10 seconds to test
    SESSION_SAVE_EVERY_REQUEST = True