Flask中如何让auth_level会话变量关闭浏览器后随Flask-Login登录状态留存
解决方案
问题根源
默认Flask的session是会话级Cookie,用户关闭浏览器就会被自动清除;而Flask-Login的remember=True是独立的持久化Cookie,有效期和session完全无关,因此会出现记住登录仍生效,但session中auth_level丢失的问题。
方案1:调整session为持久化(改动最小,适配大多数场景)
直接对齐session和Flask-Login记住登录的有效期即可:
- 首先在Flask全局配置中统一两者的有效期:
from datetime import timedelta # 两者设为相同的有效期,比如30天 app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=30) app.config['REMEMBER_COOKIE_DURATION'] = timedelta(days=30)
- 在用户完成TFA校验、设置
auth_level=2的逻辑处,标记session为持久化:
# TFA校验通过的逻辑片段 session['auth_level'] = 2 # 仅当用户勾选了「记住我」时才设置持久化,未勾选则保持会话级 if current_user.is_remembered: # 或者替换为你自己的记住状态判断变量 session.permanent = True session.modified = True
- 原有退出登录逻辑无需额外修改,
logout_user()会自动清理remember cookie,session也会同步失效。
注意:Flask默认的session是加密签名的,用户无法篡改内容,该方案安全性足够。如果使用服务端session(如Redis存储),同样适配该逻辑。
方案2:绑定TFA状态到记住机制(安全性更高,适合高要求场景)
如果不想依赖session的存储状态,可以将TFA认证信息和用户的remember_token绑定存储,完全对齐有效期:
- 给用户模型新增两个字段:
last_tfa_verified_at:datetime类型,记录最近一次TFA校验通过时间tfa_remember_token:字符串类型,存储TFA校验的唯一标识
- TFA校验通过时,生成独立的TFA持久化Cookie:
import secrets from flask import make_response # TFA校验通过逻辑片段 tfa_token = secrets.token_hex(32) current_user.tfa_remember_token = tfa_token current_user.last_tfa_verified_at = datetime.utcnow() db.session.commit() resp = make_response(redirect(url_for('main.home'))) # 配置TFA Cookie参数和remember Cookie完全一致 resp.set_cookie( 'tfa_remember', value=tfa_token, max_age=app.config['REMEMBER_COOKIE_DURATION'], secure=app.config['SESSION_COOKIE_SECURE'], httponly=True, samesite=app.config['SESSION_COOKIE_SAMESITE'] ) return resp
- 修改
@tfa_login_required装饰器,新增TFA Cookie校验逻辑:
@wraps(f) @login_required def decorated_function(*args, **kwargs): auth_level = session.get('auth_level') # session无auth_level时自动校验TFA Cookie if auth_level != 2: tfa_cookie = request.cookies.get('tfa_remember') if tfa_cookie and current_user.tfa_remember_token == tfa_cookie: session['auth_level'] = 2 session.permanent = True auth_level = 2 # 原有校验逻辑不变 if current_user.tfa_enabled and auth_level != 2: return redirect(url_for('auth.login_view')) return f(*args, **kwargs)
- 修改退出登录逻辑,清理TFA Cookie和用户存储的标识:
@auth.route('/logout/') @login_required def logout(): logout_user() current_user.tfa_remember_token = None db.session.commit() session['auth_level'] = 0 session.modified = True resp = make_response(redirect(url_for('main.home'))) resp.delete_cookie('tfa_remember') return resp
内容的提问来源于stack exchange,提问作者Nyxshield
相关产品推荐
相关产品推荐

