Flask-CORS 默认全局放行存在严重安全隐患,必须显式指定origins且禁用"*",需配合supports_credentials=True处理Cookie,局部装饰器优于全局配置,静态文件和预检请求需单独处理。

Flask-CORS 默认全局放行太危险,别直接 cors = CORS(app)
默认不带任何参数调用 CORS(app) 会允许所有源(*)跨域请求,但一旦涉及 Cookie、认证头或非简单请求,浏览器就会拒绝——因为 Access-Control-Allow-Origin: * 和 credentials: true 冲突。这不是配置没生效,是浏览器强制拦截。
实操建议:
- 始终显式指定
origins参数,哪怕开发期也写成["http://localhost:3000"],别偷懒留空 - 需要传 Cookie 时,必须同时设
supports_credentials=True,且origins不能为*,得是具体域名列表 - 生产环境禁止用
origins="*",哪怕加了supports_credentials=False也不安全——攻击者可伪造 Origin 头试探接口
局部跨域控制:给单个路由加 @cross_origin 比全局更灵活
不是所有接口都要跨域,比如管理后台的 /api/v1/users 需要前端调,但 /healthz 或内部定时任务用的 /api/internal/xxx 就不该暴露。全局配置一刀切反而埋雷。
实操建议:
- 用
@cross_origin(origins=["https://myapp.com"], supports_credentials=True)装饰具体视图函数,比改全局配置更精准 - 多个路由共用同一策略?把参数提成变量,避免硬编码重复:
frontend_origins = ["https://a.com", "https://b.com"],然后每个装饰器里引用它 - 注意:如果已启用全局
CORS(app),局部装饰器会覆盖全局设置——这是好事,但得意识到覆盖逻辑存在,别以为加了局部装饰就“额外多开一个口子”
send_file 和静态文件路由容易漏掉跨域头
Flask 默认的 send_file、send_from_directory 或静态文件路由(如 app.static_folder)不会自动继承 CORS 配置,返回的响应里压根没有 Access-Control-Allow-Origin。前端拿不到图片、PDF 或 JS/CSS 文件时,控制台只报“CORS error”,根本看不出是静态资源出问题。
实操建议:
- 对
send_file手动加响应头:from flask import make_response<br>resp = make_response(send_file(path))<br>resp.headers['Access-Control-Allow-Origin'] = 'https://myapp.com'<br>return resp
- 静态文件目录需要跨域?别依赖
CORS扩展,改用app.add_url_rule自定义路由,再套@cross_origin - 如果用 Nginx 做反向代理,直接在 Nginx 层加
add_header 'Access-Control-Allow-Origin' 'https://myapp.com';更干净,Flask 层不用管静态资源
调试跨域失败:先看 Network 面板里的预检请求(OPTIONS)
很多同学看到 “No 'Access-Control-Allow-Origin' header” 就去翻 Flask 日志,结果发现请求压根没进 Flask——因为浏览器先发了个 OPTIONS 预检,而 Flask 默认不处理 OPTIONS,直接 405。这时候改 CORS 配置没用,得先让预检通过。
实操建议:
- 检查 Network 面板,找状态码为 405 或 404 的 OPTIONS 请求,确认是不是预检被拦住
-
CORS扩展会自动响应预检,但前提是:路由存在、没被其他装饰器(比如自定义鉴权)提前 return、没触发 404 —— 所以确保被跨域的路由本身能正常访问 - 用
curl -v -X OPTIONS http://localhost:5000/api/data模拟预检,看响应头有没有Access-Control-Allow-Methods,没有说明CORS没生效或被中间件截断
跨域真正麻烦的从来不是配哪行代码,而是搞清当前请求到底卡在哪一层:是 DNS、Nginx、WAF、Flask 路由、还是浏览器策略。每次出问题,先盯死 Network 面板里那个 OPTIONS 请求的完整生命周期。










