如何正确配置Flask的CORS与Authorization Header?权限路由访问异常
我之前也碰到过一模一样的问题——CORS(app)能搞定简单请求,但一涉及带Authorization头的接口就崩,本质是预检请求(OPTIONS)的处理没到位,还有CORS配置没明确允许自定义头。下面给你一步步解决的方案:
1. 先搞懂为什么带Authorization头会报错
浏览器把请求分成「简单请求」和「非简单请求」,带Authorization、Content-Type为application/json这类都属于非简单请求。浏览器会先自动发一个OPTIONS请求去服务器“预检”,确认服务器允许这个请求的来源、头、方法,如果服务器没正确响应OPTIONS请求,就会抛出你看到的那个跨域错误。
2. 调整CORS配置,明确允许所需的头和方法
不要只用CORS(app)这种默认配置,要针对性设置资源路由、允许的来源、头和方法:
from flask import Flask from flask_cors import CORS app = Flask(__name__) # 精准配置需要跨域的路由(比如/api下的所有接口) CORS(app, resources={ r"/api/*": { "origins": "http://localhost:3000", # 替换成你的React应用域名 "allow_headers": ["Authorization", "Content-Type"], # 必须包含Authorization "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"], # 要包含OPTIONS方法 "supports_credentials": True # 如果你的认证需要带cookie,加上这个 } })
⚠️ 注意:origins不要用*,因为当请求带Authorization或凭证时,浏览器不允许用通配符,必须明确写前端的域名。
3. 确保OPTIONS请求不会被认证拦截
如果你用了Flask的认证装饰器(比如@login_required或者自定义的权限校验装饰器),这些装饰器可能会拦截OPTIONS请求——因为OPTIONS请求里不会带Authorization头,直接就返回401了,导致跨域失败。
解决方法是在请求处理前先放行OPTIONS请求:
from flask import request @app.before_request def handle_preflight(): if request.method == 'OPTIONS': return '', 200
或者在你的认证装饰器里加判断:
from functools import wraps def auth_required(f): @wraps(f) def decorated_function(*args, **kwargs): # 放行OPTIONS请求 if request.method == 'OPTIONS': return f(*args, **kwargs) # 你的认证逻辑... token = request.headers.get('Authorization') if not token: return {"error": "Unauthorized"}, 401 # 其他校验步骤 return f(*args, **kwargs) return decorated_function
4. 前端fetch请求的配套设置
如果你的请求需要带凭证(比如cookie),要在fetch里加上credentials: 'include';同时确保headers正确设置:
fetch('/api/your-protected-route', { method: 'GET', headers: { 'Authorization': `Bearer ${yourToken}`, 'Content-Type': 'application/json' }, credentials: 'include' // 和后端的supports_credentials对应 }) .then(response => response.json()) .catch(err => console.error(err));
5. 验证配置是否生效
可以用curl手动发OPTIONS请求测试:
curl -X OPTIONS \ -H "Origin: http://localhost:3000" \ -H "Access-Control-Request-Method: GET" \ -H "Access-Control-Request-Headers: Authorization" \ http://localhost:5000/api/your-protected-route
看响应头里有没有这些字段:
Access-Control-Allow-Origin: http://localhost:3000Access-Control-Allow-Headers: Authorization,Content-TypeAccess-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
如果有,说明CORS配置已经生效了。
按这个流程走下来,带Authorization头的跨域请求应该就能正常工作了!
内容的提问来源于stack exchange,提问作者kidman01

