烧瓶永久会话:在哪里定义它们?

Posted

技术标签:

【中文标题】烧瓶永久会话:在哪里定义它们?【英文标题】:Flask permanent session: where to define them? 【发布时间】:2016-03-11 03:24:42 【问题描述】:

默认情况下,Flask 使用 volatile 会话,这意味着会话 cookie 设置为在浏览器关闭时过期。为了使用永久会话,它将使用具有已定义过期日期的 cookie,应设置session.permanent = True,就像mentioned in this question. 一样,过期日期将基于config['PERMANENT_SESSION_LIFETIME'] 设置。

我很惊讶配置文件中定义了会话生命周期,但无法通过配置请求使用永久会话,例如config['USE_PERMANENT_SESSION'] = True。但就这样吧。

我的问题是:如果您确实想要永久会话,那么定义它们的最佳位置是什么?它是否在提到的问题中提出的@app.before_request 函数中?但这意味着在每次请求时重新设置它?似乎一旦设置,session.permanent 将在会话结束之前保持为真。

永久会话通常在登录后使用,因此请求它们的最佳位置可能是在处理login_user() 时?那么,对所有匿名页面使用易失性会话 cookie 并通过在登录时执行 session.permanent = True 切换到永久会话的最佳策略是什么?

根据是普通的session cookie 还是remember_me cookie,可能需要设置不同的生命周期。实现这一目标的最佳方法是什么?

【问题讨论】:

【参考方案1】:

我很惊讶没有回答这个问题。似乎应该有某种类型的配置变量SESSION_PERMANENT = True。但不幸的是没有。正如您所提到的,这是最好的方法。

@app.before_request
def make_session_permanent():
    session.permanent = True

【讨论】:

是 config['PERMANENT_SESSION_LIFETIME'] 值以秒还是毫秒为单位? @dashesy,您指的是Flask-Session 扩展中的配置。在 vanilla Flask 会话管理中,config['SESSION_PERMANENT'] 不存在,甚至在 master 分支中也不存在。 @RandomCOSMOS app.config['PERMANENT_SESSION_LIFETIME'] 的值以秒为单位,您可以在文档中看到:flask.palletsprojects.com/en/2.0.x/config/…【参考方案2】:

你应该使用PERMANENT_SESSION_LIFETIMEsession.permanent吗?

您真正想要做的可能是使用户的登录状态过期。但是,此配置会使包含用户登录状态以及(可能)存储在session 中的其他一些数据的会话对象/cookie 过期。

需要设置session.permanent吗?

根据Flask's doc:

Flask 的默认 cookie 实现会验证加密签名不​​早于该值。

session.permanentPERMANENT_SESSION_LIFETIME 的附加组件。有时,如果您不将session.permanent 设置为 True,也可以。

如果不设置session.permanent,会话cookie的生命周期将不受PERMANENT_SESSION_LIFETIME的影响。但是 Flask 会查看PERMANENT_SESSION_LIFETIME 和会话 cookie 中的时间戳,以查看会话 cookie 是否仍然有效。如果时间戳比PERMANENT_SESSION_LIFETIME 指定的时间戳太旧,它将被忽略。但是cookie仍然存在。

这就是 Flask 忽略会话 cookie 的方式:

def open_session(self, app, request):
    s = self.get_signing_serializer(app)
    if s is None:
        return None
    val = request.cookies.get(app.session_cookie_name)
    if not val:
        return self.session_class()
    max_age = total_seconds(app.permanent_session_lifetime)
    try:
        data = s.loads(val, max_age=max_age)
        return self.session_class(data)
    except BadSignature:
        return self.session_class()

如果您设置session.permanent=True,验证仍将完成。而且,会话cookie会在PERMANENT_SESSION_LIFETIME之后过期并从浏览器中删除。

这是PERMANENT_SESSION_LIFETIME控制cookie过期的方式:

def get_expiration_time(self, app, session):
    if session.permanent:
        return datetime.utcnow() + app.permanent_session_lifetime


def save_session(self, app, session, response):
    ...
    expires = self.get_expiration_time(app, session)
    val = self.get_signing_serializer(app).dumps(dict(session))
    response.set_cookie(
        app.session_cookie_name,
        val,
        expires=expires,
        httponly=httponly,
        domain=domain,
        path=path,
        secure=secure,
        samesite=samesite
    )

是否需要为每个请求设置session.permanent

session.permanent 默认情况下实际上是session['_permanent']。它的值将保持在session。 但是,如果您打算仅在用户登录时分配它,请通过检查用户如何绕过登录路径进行登录来保持警惕。例如,通过注册。

【讨论】:

非常详细且有用的答案,您能否详细说明用户如何通过注册绕过登录路线? @oeter 假设您的服务的用户体验旨在让用户在注册后进入登录状态,因此用户无需在注册后立即登录。然后,您服务中的注册逻辑可能会包含授予会话的逻辑,该逻辑可能与登录逻辑共享,也可能不共享。【参考方案3】:

我选择你说的“login_user()”

@asset.route('/login', methods=['GET', 'POST'])
def login():
    #After Verify the validity of username and password
    session.permanent = True

如果它设置在 app.before_request,这将导致设置它们太多次。

【讨论】:

您是否考虑过session['_permanent']可以设置为false或从客户端发出的请求中删除?这将导致绕过过期时间的验证。

以上是关于烧瓶永久会话:在哪里定义它们?的主要内容,如果未能解决你的问题,请参考以下文章

是否有一种简单的方法可以在烧瓶中使会话超时?

设置定义关闭永久

如何在 Linux 中永久设置环境变量

Databricks - 创建永久用户定义函数 (UDF)

Linux 命令别名 alias永久生效

Linux 命令别名,让alias永久生效