升级Flask-Login至0.6.3后Azure Web App会话过期失效问题排查
Flask-Login 0.6.3升级后Azure Web App会话过期不自动登出问题
问题背景
在Azure Web App上部署的Flask应用采用默认配置(无额外工作进程),将Flask-Login从0.6.0升级到0.6.3后,出现会话过期时无法自动登出的问题:
- 本地环境:会话1分钟过期后刷新页面,会自动重定向到登录页并显示提示信息,功能正常。
- Azure生产环境:会话过期后不会触发重定向,且会话Cookie内容发生异常变化。
相关代码
init.py
def create_app(config_env=os.getenv("ENV"), register_blueprints=True): app = Flask(__name__) app.config.from_object(config[config_env]) db.init_app(app) lm.init_app(app) lm.login_view = "auth.login" lm.login_message_category = "info" lm.refresh_view = "auth.login" lm.needs_refresh_message = "Session timedout, please re-login" lm.login_message_category = "info" @app.before_request def my_func(): session.modified = True @app.before_request def before_request(): session.permanent = True current_app.permanent_session_lifetime = timedelta(minutes=1)
model.py
@lm.user_loader def load_user(user_id): return PortalUsers.query.get(int(user_id)) class PortalUsers(UserMixin, db.Model): __tablename__ = "tbl_PortalUsers" id = db.Column("Staff_Id", db.Integer, primary_key=True) first_name = db.Column("First_Name", db.String(100, "SQL_Latin1_General_CP1_CI_AS")) last_name = db.Column("Last_Name", db.String(100, "SQL_Latin1_General_CP1_CI_AS")) full_name = db.Column( db.String(201, "SQL_Latin1_General_CP1_CI_AS"), db.Computed("(([First_Name]+' ')+[Last_Name])", persisted=False), ) phone = db.Column("Phone", db.String(10, "SQL_Latin1_General_CP1_CI_AS")) email = db.Column("Email", db.String(50, "SQL_Latin1_General_CP1_CI_AS")) role_type = db.Column("Role_Type", db.String(20, "SQL_Latin1_General_CP1_CI_AS")) portal_active = db.Column("Portal_Active", db.Integer) date_created = db.Column("Date_Created", db.DateTime, default=datetime.utcnow) created_by = db.Column("Created_By", db.String(100, "SQL_Latin1_General_CP1_CI_AS")) last_updated = db.Column("Last_Updated", db.DateTime, default=datetime.utcnow) last_updated_by = db.Column( "Last_Updated_By", db.String(100, "SQL_Latin1_General_CP1_CI_AS") ) date_deleted = db.Column("Date_Deleted", db.DateTime) time_zone_id = db.Column( "TimeZoneId", db.Integer, db.ForeignKey("tbl_TimeZones.id"), unique=False, nullable=False, default=1, ) password = db.Column("Password", db.String(64), nullable=False)
最新排查信息
对比本地与生产环境的会话Cookie:
- 本地环境:会话过期后的Cookie可解析为合法JSON数据。
- 生产环境:会话过期或登出后的Cookie无法解析为JSON,推测问题与Flask会话机制相关,寻求具体排查方向。
排查方向建议
- 检查Azure Web App的代理/网关配置:确认是否有ARR(Application Request Routing)或前端代理修改了会话Cookie的内容,比如开启了Cookie加密、压缩或改写,导致Flask无法正确解析Cookie数据。
- 验证SECRET_KEY一致性:确保生产环境和本地的
SECRET_KEY完全一致,无额外空格或特殊字符。Flask依赖该密钥加密/解密会话数据,不一致会导致解密失败,生成空会话,从而绕过Flask-Login的过期检测。 - 分析Flask-Login版本变更:对比0.6.0到0.6.3的版本差异,重点关注会话验证、Cookie处理逻辑的改动,比如是否新增了会话签名校验规则,导致生产环境的旧Cookie不符合新校验标准。
- 调整会话生命周期配置:将
PERMANENT_SESSION_LIFETIME的配置移到应用初始化阶段(app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=1)),避免在before_request中动态设置可能引发的上下文异常。 - 查看生产环境日志:开启Flask的DEBUG/INFO级日志,记录会话Cookie的解密过程,检查是否存在
BadSignature等解密失败的异常,这类异常会导致Flask生成新的空会话,无法触发登出逻辑。 - 核对Cookie属性:用浏览器开发者工具对比本地和生产环境的会话Cookie属性(HttpOnly、Secure、SameSite),Azure Web App可能强制启用Secure Cookie(当HTTPS开启时),若本地用HTTP测试,需确保
SESSION_COOKIE_SECURE配置与环境匹配。
内容的提问来源于stack exchange,提问作者ghawes
相关产品推荐
相关产品推荐

