即使在 Flask 中关闭浏览器后,如何将一个会话变量存储一段时间?

Posted

技术标签:

【中文标题】即使在 Flask 中关闭浏览器后,如何将一个会话变量存储一段时间?【英文标题】:How do I store one session variable for some time even after closing the browser in Flask? 【发布时间】:2021-12-28 07:39:18 【问题描述】:

我正在使用 Flask-Login 的函数 login() 和 remember=True。

这工作正常。但最近我实现了双因素身份验证,用户必须下载身份验证器应用才能登录。

我创建了自己的 @tfa_required 装饰器,它使用 @login_required 以防用户启用 TFA。我跟踪登录状态的方法是使用名为auth_level 的会话变量来了解用户是否使用 TFA 成功登录。 (附上代码sn-ps)。

假设用户登录到浏览器然后关闭它。他仍然会登录(因为他使用 remember = True 登录),但他将不得不再次进入 TFA(auth_level=1 - 意味着 TFA 尚未成功 - 现在而不是 auth_level=2)。

我真正想要的是存储 auth_level 会话变量,只要 Flask-Login 记得用户登录,即使在关闭浏览器之后也是如此。

据我了解,Flask-Login 使用不同的会话来存储与登录相关的变量,以便用户在一段时间内仍处于登录状态。

如何让客户端即使在关闭浏览器后也能记住auth_level

谢谢。

# Decorator for TFA-required views
def tfa_login_required(f):
    """Implement additional TFA checking, on top of login_required.

    TFA is only checked if it has been activated for the user.
    """
    @wraps(f)
    @login_required
    def decorated_function(*args, **kwargs):
        # if the user is authenticated and has tfa enabled but not tfa passed
        if (
            current_user.tfa_enabled
            and session.get('auth_level') != 2
        ):
            return redirect(url_for('auth.login_view'))
        # if authenticated proceed normally
        else:
            return f(*args, **kwargs)
    return decorated_function

使用 login_required 没有 tfa_required 的示例:

@auth.route('/logout/')
@login_required
def logout():
    logout_user()
    session['auth_level'] = 0
    session.modified = True
    return redirect(url_for('main.home'))

同时使用 tfa_required 和 login_required 的示例:

@main.route('/some_route/', methods=['GET'])
@tfa_login_required
def some_route():
    do_some_work_that_requires_full_authentication()

【问题讨论】:

【参考方案1】:

您可能正在寻找this

默认情况下,如果选项卡关闭,Flask 会删除所有会话数据。为了使其永久化,请执行以下操作:

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

【讨论】:

【参考方案2】:

我最终使用 Flask-Login cookie 本身将变量包含在 Flask-Login cookie 中。供参考,代码如下:

from flask_login import (
....
COOKIE_DURATION,
COOKIE_SECURE,
COOKIE_HTTPONLY,
encode_cookie,
)

在视图函数中,我没有返回url_for(...),而是使用make_response() 创建一个响应对象,并使用以下内容设置响应cookie:

    response = make_response(redirect(url_for('...')))

    # Setting cookie similar to Flask Login way of setting its cookies
    duration = current_app.config.get('REMEMBER_COOKIE_DURATION', COOKIE_DURATION)
    secure = current_app.config.get('REMEMBER_COOKIE_SECURE', COOKIE_SECURE)
    httponly = current_app.config.get('REMEMBER_COOKIE_HTTPONLY', COOKIE_HTTPONLY)
    expires = duration + datetime.utcnow()

    # encode additional data to ensure that the user cannot simply use the value
    # from the remember cookie
    data = encode_cookie(str(session['_user_id']) + '_cookie_variable')

    response.set_cookie(
        'cookie_variable',
        value=data,
        expires=expires,
        secure=secure,
        httponly=httponly
    )
    return response

【讨论】:

以上是关于即使在 Flask 中关闭浏览器后,如何将一个会话变量存储一段时间?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 中关闭浏览器上的会话

即使用户在android studio中关闭应用程序,如何保持登录状态

在 Facebook-Ios-Sdk 中关闭 Facebook 会话

如何在 Spring Security 中关闭 HTTP 会话超时?

如何在 symfony 2/3 中关闭会话?

当我在 Android Web 浏览器中关闭运行 CodeIgniter Web 应用程序的 Android 应用程序时,CodeIgniter 会话不会关闭