由于在Django中处于非活动状态,如何过期会话?

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

  1. 用户closures浏览器时会话过期。
  2. 会话经过一段时间不活动后会过期。
  3. 当会话由于不活动而到期时检测并向用户显示适当的消息。
  4. 在不活动期结束之前的几分钟,警告即将到来的会话过期的用户。 除了警告之外,还要为用户提供延长会话的选项。
  5. 如果用户在应用程序中处理长时间的业务活动而不涉及发送到服务器的请求,则该会话不能超时。

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

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

要求2
我已经看到一些build议,使用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在浏览器closures时或在指定的到期时间到期。 如果使用SESSION_COOKIE_AGE,并且用户在cookie过期之前closures浏览器,则Cookie被保留,并且重新打开浏览器将允许用户(或任何其他人)进入系统而不被重新authentication。

  • Django只依赖存在的cookie来确定会话是否处于活动状态。 它不会检查与会话一起存储的会话过期date。

下面的方法可以用来实现这个要求,并解决上面提到的问题。

  • 不要设置SESSION_COOKIE_AGE。
  • 将会话的终止date设置为每个请求的“当前时间+不活跃期”。
  • 在SessionMiddleware中覆盖process_request并检查会话是否到期。 如果会话已过期,请放弃。

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

要求4
使用JavaScript来检测用户不活动,提供警告,还可以select扩展会话。 如果用户希望扩展,发送一个保活脉冲给服务器来扩展会话。

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


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

任何见解将不胜感激。

这是一个想法…使用SESSION_EXPIRE_AT_BROWSER_CLOSE设置closures浏览器的会话。 然后在每个请求的会话中设置一个时间戳,像这样。

 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 

然后你只需要build立一些URL和视图就可以将有关的数据返回到关于session届满的ajax调用。

当用户select“更新”会话时,可以这么说,你所要做的就是将requeset.session['last_activity']设置为当前时间

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

Django的会话安全性只是… …

…有一个额外的要求:如果服务器没有响应或攻击者断开互联网连接:它应该过期无论如何。

Disclamer:我维护这个应用程序。 但是我一直在观察这个线程很长一段时间:)

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

 SESSION_COOKIE_AGE = 600 #10 minutes. 

但是,只有这样做,会话将在10分钟后过期,无论用户是否展示一些活动。 为了解决这个问题,每当用户用下面的语句执行任何一种请求时,到期时间可以自动更新(再过10分钟):

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

我只是相当新的使用Django。

如果login的用户closures浏览器或者处于空闲状态(非活动超时)一段时间,我想使会话过期。 当我把它弄清楚的时候,这个SOF问题首先出现了。 感谢很好的回答,我查了资源,以了解中间件在Django的请求/响应周期中是如何工作的。 这是非常有益的。

在这里,我正要将自定义中间件应用到我的代码中。 但是我还是有点怀疑,因为这里最好的答案是在2011年编辑的。我花了更多的时间从最近的search结果中search一点点,并提出了一个简单的方法。

 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,closures浏览器时会话过期。 2.只有当我空闲超过10秒钟,会话过期。 感谢SESSION_SAVE_EVERY_REQUEST,每当你发生新的请求,它会保存会话和更新超时到期

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

请注意,会话cookie仅在创build或修改会话时发送。 如果SESSION_SAVE_EVERY_REQUEST为真,会话cookie将在每个请求中发送。

同样,每次会话cookie发送时,会话cookie的expires部分都会更新。

django手册1.10

我只是留下回答,以便像我这样的Django中的一些新人不会像我一样花费很多时间来找出解决scheme。

也可以在函数中使用stackoverflow构build

 SESSION_SAVE_EVERY_REQUEST = True 

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

 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