You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 19:12:41