Flask-Session与CORS异常:跨请求Session为空,部分请求CORS失败
Flask-Session跨端点丢失Session及CORS异常问题解决
问题概述
遇到CORS异常,导致Flask-Session无法在不同端点的请求间保留变量,前后端无法正常传递Cookie。具体表现:
- 前端运行在
http://localhost:3000,后端运行在http://localhost:5000 - 首次请求
/file_upload成功,后端生成对应Session ID并设置session['test'] = 0 - 第二次请求
/allin_6_9时,后端生成新的Session ID,读取session['test']触发KeyError,返回500错误 - 浏览器控制台显示CORS错误
- 已更新所有依赖至最新版本:Flask 3.0.0、Werkzeug 3.0.1、Flask-Cors 4.0.0、Flask-Session 0.5.0
原前端代码
import React, { useState } from "react"; import "./App.css"; const uploadFile = async () => { if (!file) return; setIsLoading(true); try { const formData = new FormData(); formData.append("file", file); const response = await fetch( `${URI}/file_upload`, { method: "POST", body: formData, }, { credentials: 'include' } // 错误:fetch仅接受两个参数,此配置未生效 ); } catch (error) { ... } }
原后端代码
from flask import Flask, session from flask_session import Session from flask_cors import CORS, cross_origin app = Flask(__name__) app.secret_key = 'BAD_SECRET_KEY' UPLOAD_FOLDER = 'uploads' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['SESSION_TYPE'] = 'filesystem' Session(app) # 错误:supports_credentials=True时,origins不能设为通配符* CORS(app, supports_credentials=True, resources={r"*": {"origins": "*"}}, withCredentials = True) @app.route('/file_upload', methods=['POST']) @cross_origin(supports_credentials=True) # 重复配置,可能引发冲突 def upload_parse_file(): # some code here ... print('sessions_sid', session.sid) session['test'] = 0 return 'OK' @app.route('/allin_6_9', methods=['POST']) @cross_origin(supports_credentials=True) # 重复配置,可能引发冲突 def rfi(): print('sessions_sid', session.sid) print('session test is', session['test']) return 'OK'
问题根源与修复方案
1. 前端fetch参数错误
fetch API仅接受两个参数:请求URL和配置对象。原代码将credentials: 'include'作为第三个参数传入,导致该配置未生效,浏览器不会携带Cookie到后端。
修复后前端代码:
import React, { useState } from "react"; import "./App.css"; const uploadFile = async () => { if (!file) return; setIsLoading(true); try { const formData = new FormData(); formData.append("file", file); const response = await fetch( `${URI}/file_upload`, { method: "POST", body: formData, credentials: 'include' // 移至第二个参数的配置对象中 } ); } catch (error) { ... } }
注意:所有跨域请求(包括
/allin_6_9的请求)都需要添加credentials: 'include'配置。
2. 后端CORS配置冲突
当启用supports_credentials=True时,浏览器不允许将origins设为通配符*,这是CORS安全规范的要求。同时,全局配置CORS后,无需再给每个路由添加@cross_origin装饰器,重复配置可能导致冲突。
修复后后端CORS配置:
# 替换原CORS配置,指定具体前端Origin CORS(app, supports_credentials=True, resources={r"*": {"origins": "http://localhost:3000"}})
移除所有路由上的
@cross_origin(supports_credentials=True)装饰器。
3. Flask Session Cookie跨域配置
跨域场景下,需要确保Session Cookie的SameSite属性设置正确,否则浏览器不会在跨域请求中携带Cookie。
在后端添加以下配置:
# 跨域场景下,SameSite设为None,同时开启Secure(本地http环境可临时关闭,生产环境必须开启) app.config['SESSION_COOKIE_SAMESITE'] = 'None' app.config['SESSION_COOKIE_SECURE'] = False # 本地http开发用False,生产环境改True # 本地开发可省略Domain配置,浏览器会自动处理localhost # app.config['SESSION_COOKIE_DOMAIN'] = 'localhost'
4. 完整修复后后端代码
from flask import Flask, session from flask_session import Session from flask_cors import CORS app = Flask(__name__) app.secret_key = 'BAD_SECRET_KEY' UPLOAD_FOLDER = 'uploads' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER # Session配置 app.config['SESSION_TYPE'] = 'filesystem' app.config['SESSION_COOKIE_SAMESITE'] = 'None' app.config['SESSION_COOKIE_SECURE'] = False # 本地http开发用False,生产环境改True Session(app) # CORS配置:指定具体Origin,启用credentials CORS(app, supports_credentials=True, resources={r"*": {"origins": "http://localhost:3000"}}) @app.route('/file_upload', methods=['POST']) def upload_parse_file(): # some code here ... print('sessions_sid', session.sid) session['test'] = 0 return 'OK' @app.route('/allin_6_9', methods=['POST']) def rfi(): print('sessions_sid', session.sid) # 添加容错处理,避免KeyError导致500 test_value = session.get('test', 'default_value') print('session test is', test_value) return 'OK'
验证步骤
- 重启后端服务
- 前端发起
/file_upload请求,查看浏览器Application面板的Cookie,确认已设置Session Cookie - 发起
/allin_6_9请求,查看后端日志,两次请求的session.sid应一致,session['test']能正常读取
内容的提问来源于stack exchange,提问作者Vladimir Kuzmenkov
相关产品推荐
相关产品推荐

