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

Flask与前端会话持久化问题:登录成功后会话丢失

Flask-Login跨域会话持久化问题解决方案

问题背景

使用Flask作为后端(运行地址http://127.0.0.1:5000)、Angular作为前端(运行地址http://localhost:4200)开发Web应用,通过Flask-Login实现登录系统,但登录成功后会话无法持久,受保护路由无法识别已认证用户。

问题描述

登录成功后,后端已在浏览器中设置会话Cookie,但访问受保护路由(如http://127.0.0.1:5000/api/player/info)时,服务器返回{"is_authenticated": false},表明会话未被正确识别。

代码示例

init.py

import os
from flask import Flask
from flask_cors import CORS
from flask_login import LoginManager
from flask_session import Session

from .database import db, migrate
from .models import Player


# Initialize app for Flask-Login
login_manager = LoginManager()
login_manager.login_view = 'auth.login'


@login_manager.user_loader
def load_user(user_id):
    return Player.query.get(int(user_id))


def create_app():
    app = Flask(__name__)
    env_config = os.getenv("APP_SETTINGS", "config.DevelopmentConfig")
    app.config.from_object(env_config)

    # Initialize app for Flask-Session
    Session(app)

    # Handle CORS (Cross-Origin Resource Sharing)
    CORS(app, supports_credentials=True)

    # Initialize app for SQLAlchemy
    db.init_app(app)

    # Initialize app for Flask-Login
    login_manager.init_app(app)

    # Initialize app for Flask-Migrate
    migrate.init_app(app, db)

    # Register blueprints
    from .blueprints import auth_bp, player_bp
    app.register_blueprint(auth_bp, url_prefix="/api/auth")
    app.register_blueprint(player_bp, url_prefix="/api/player")
  
    return app

Flask登录路由

@auth_bp.route('/login', methods=['POST'])
def login():
    # ... [authentication logic] ...
    login_user(user, remember=remember)
    return jsonify({"message": "Logged in successfully"}), 200

获取玩家信息的Flask路由

@player_bp.route('/info', methods=['GET'])
def get_player_info():
    if current_user.is_authenticated:
        return {"is_authenticated": True, "name": current_user.name}
    return {"is_authenticated": False}

Angular登录服务(TypeScript)

login(userData: { username: string; password: string; remember: boolean }): Observable<any> {
    const url = `127.0.0.1:5000/api/auth/login`;
    return this.http.post(url, userData, { withCredentials: true });
}

已排查步骤

  • 登录函数已完成用户认证并调用login_user(user, remember=remember)
  • CORS配置了supports_credentials=True处理跨域请求
  • Angular HttpClient配置了{ withCredentials: true }确保请求携带会话Cookie
  • 验证登录后浏览器已设置会话Cookie
  • 确认后续请求的请求头已携带会话Cookie至服务器
  • 尝试过Flask默认会话管理和Flask-Session结合Redis的方式,问题仍存在
  • 使用基础HTML+JS页面在不同端口测试,仍出现相同会话持久化问题,排除Angular相关问题

解决方案思路

1. 统一前后端主机名

浏览器会将localhost和127.0.0.1视为不同域名,导致Cookie跨域无法正常传递。将前端运行地址改为http://127.0.0.1:4200,同时修改Angular登录请求的URL为完整HTTP地址:

const url = `http://127.0.0.1:5000/api/auth/login`;

2. 显式配置CORS允许的源

当supports_credentials=True时,CORS不能使用通配符*作为origins,需指定具体前端地址:

CORS(app, origins="http://127.0.0.1:4200", supports_credentials=True)

3. 调整Flask会话Cookie配置

在Flask配置文件(如config.DevelopmentConfig)中添加以下配置,确保Cookie跨域可用:

SESSION_COOKIE_DOMAIN = '127.0.0.1'
SESSION_COOKIE_SAMESITE = 'Lax'  # 开发环境用Lax,生产环境跨域可设为None(需配合Secure=True)
SESSION_COOKIE_SECURE = False  # 开发环境关闭,生产环境HTTPS下开启

4. 验证Flask-Login的user_loader函数

确保load_user函数能正确从数据库获取用户:

  • 检查user_id的类型是否与数据库中存储的用户ID类型匹配
  • 测试直接调用load_user(valid_user_id)是否能返回对应的用户对象

5. 检查浏览器Cookie设置

部分浏览器默认阻止跨域Cookie,需在浏览器设置中允许127.0.0.1域名的Cookie,或在开发环境使用浏览器隐私模式测试。


内容的提问来源于stack exchange,提问作者Marcos Treviso

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 23:00:38