【问题标题】:Django - Session expiration renewalDjango - 会话到期续订
【发布时间】:2018-07-31 09:26:23
【问题描述】:

我正在努力解决有关会话的问题。

我想知道如果用户在一段时间内(例如 15 天)没有尝试连接到网站,如何使会话过期。 换句话说,我想在他/她每次连接到网站时更新用户会话的到期日期。

我废弃了很多网站,但找不到任何有价值的例子。

【问题讨论】:

  • 您使用的是哪个版本的 Django?您可能想看看:docs.djangoproject.com/en/2.0/topics/http/sessions/…
  • 您可以在每次调用视图时使用request.session.set_expiry() 函数为会话设置新的到期日期。
  • 所以这个函数修改了 SESSION_COOKIE_AGE 还是设置了另一个参数?我不明白 set_expiry() 的调用和只是更改参数值之间的区别。

标签: python django django-sessions


【解决方案1】:

在你的 settings.py 中设置SESSION_COOKIE_AGE

SESSION_COOKIE_AGE = 15 * 60 # 15 Minutes

在文档https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SESSION_COOKIE_AGE了解更多

【讨论】:

  • 感谢您的回复。但据我了解,如果用户在下午 3:00 连接到站点,则会话将在下午 3:15 到期,无论在此时间间隔内是否有连接。我想要的是如果在下午 3:10 有连接,那么到期时间设置为下午 3:25。
  • 如果有人偶然发现了这一点,那么上面的说法是不正确的。 Django 不会为每个请求发送一个新的会话 cookie,因此会话将在下午 3.15 超时并且用户必须登录。可以设置 SESSION_SAVE_EVERY_REQUEST 但这会影响性能,因为会话会在每个请求上写入数据库跨度>
  • @SebastianSchuon,作为解决 SESSION_SAVE_EVERY_REQUEST 资源繁重的解决方法,创建中间件以根据上次使用情况将 request.session.set_expiry() 更改为所需的任何时间框架是一个简单的解决方案
【解决方案2】:

我目前在我的一个系统中实施的一个很好的解决方案是,如果您希望会话在每个请求上自动更新,那么您可以编写中间件来更改会话的到期时间,以便在您需要的任何视图中进行扩展。

注意:此解决方案确实为每个请求进行 2 次数据库查询。 1 用于读取,1 用于更新。这是一个非常小的开销(使用调试工具栏最多调用通常只有几个 MS),但它是存在的。

例如:

from functools import wraps
from [project] import settings

class CookieMiddleware(object):
    """
    This middleware sets the login cookie to update timeout on every request
    """

    def __init__(self, get_response):
        self.get_response = get_response

    @staticmethod
    def process_view(request, view_func, args, kwargs):
        # ensure that we don't want to exclude this from running
        if getattr(view_func, 'cookie_not_important', False):
            print('cookie not important:', view_func.__name__)
            return None

        # the cookie is set, let's now set a new expire time to 30 minutes from now
        print('cookie expiry changed:', view_func.__name__)
        # it is probably smartest to grab this value back from settings
        expire_time = settings.SESSION_COOKIE_AGE
        # expire_time = 30 * 60
        request.session.set_expiry(expire_time)
        return view_func(request, *args, **kwargs)

    def __call__(self, request):
        response = self.get_response(request)
        return response


def cookie_not_important(view_func):
    """
    Decorator used to allow the exclusion of the cookie time being reset
    :param view_func: The view being wrapped
    :return:
    """

    def view_being_wrapped(*args, **kwargs):
        return view_func(*args, **kwargs)

    view_being_wrapped.cookie_not_important = True
    return wraps(view_func)(view_being_wrapped)

现在您可以登录并点击任何未被@cookie_not_important 包裹的视图,过期时间将根据settings.py 中的当前值重置

为了完整起见,视图看起来是这样包裹的:

from django.urls import reverse

@cookie_not_important
def logout(request):
    del request.session
    return redirect(reverse('some_view_name'))

【讨论】:

    【解决方案3】:

    这个库可能会有所帮助,它会在给定时间后注销非活动会话https://github.com/yourlabs/django-session-security

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 2017-12-02
      • 1970-01-01
      • 2011-10-22
      • 1970-01-01
      相关资源
      最近更新 更多