在前后端分离的开发模式下,前端页面和后端Flask服务通常部署在不同的域名或端口上,浏览器的同源策略会阻止前端直接发起跨域请求,此时就需要配置跨域资源共享也就是CORS来解决请求被拦截的问题。如果CORS配置不当,不仅无法解决跨域问题,还可能带来接口被恶意调用的安全隐患。

Flask基础CORS配置方法
Flask本身没有内置CORS支持,需要借助flask_cors扩展来实现跨域配置,首先需要通过pip安装该扩展:
pip install flask_cors
安装完成后,有两种常用的基础配置方式,一种是全局配置,一种是针对单个路由配置。
全局配置CORS
全局配置会让所有路由都支持跨域请求,适合前后端完全分离的场景,示例代码如下:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
# 全局开启CORS,默认允许所有来源跨域请求
CORS(app)
@app.route('/api/data')
def get_data():
return {'msg': '请求成功', 'data': [1, 2, 3]}
单个路由配置CORS
如果只需要部分接口支持跨域,可以使用cross_origin装饰器单独配置,示例代码如下:
from flask import Flask
from flask_cors import cross_origin
app = Flask(__name__)
@app.route('/api/user')
@cross_origin() # 仅该路由支持跨域
def get_user():
return {'name': '测试用户', 'age': 20}
优化CORS配置提升安全性
基础的CORS配置默认允许所有来源、所有请求方法和请求头,存在较大的安全风险,需要从以下几个方面优化配置。
限制允许的请求来源
不要使用默认的允许所有来源,应该明确指定允许的前端域名,避免未知域名的恶意请求调用接口。可以在初始化CORS时通过origins参数指定:
from flask import Flask from flask_cors import CORS app = Flask(__name__) # 仅允许指定域名跨域请求 CORS(app, origins=['https://frontend.ipipp.com', 'http://localhost:3000'])
如果需要支持多个动态来源,可以自定义来源校验函数:
from flask import Flask, request
from flask_cors import CORS
app = Flask(__name__)
def check_origin(origin):
# 校验来源是否为指定域名的子域名
if origin and origin.endswith('.ipipp.com'):
return True
return False
CORS(app, origins=check_origin)
限制请求方法和请求头
默认情况下CORS会允许所有HTTP请求方法,实际业务中通常只需要GET、POST、PUT、DELETE等部分方法,可以通过methods参数限制:
from flask import Flask from flask_cors import CORS app = Flask(__name__) # 仅允许GET、POST、PUT、DELETE方法跨域 CORS(app, methods=['GET', 'POST', 'PUT', 'DELETE'])
对于自定义请求头,也需要通过allow_headers参数明确指定,避免未知请求头带来的风险:
from flask import Flask from flask_cors import CORS app = Flask(__name__) # 仅允许Content-Type和Authorization请求头 CORS(app, allow_headers=['Content-Type', 'Authorization'])
配置凭证支持与预检缓存
如果前端请求需要携带Cookie等凭证信息,需要开启凭证支持,同时设置预检请求的缓存时间,减少不必要的预检请求:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app,
supports_credentials=True, # 允许携带凭证
max_age=86400 # 预检请求缓存时间,单位秒,这里设置为1天
)
需要注意,开启supports_credentials后,origins不能设置为通配符*,必须明确指定允许的域名,否则浏览器会拦截请求。
暴露自定义响应头
如果后端接口返回了自定义响应头,需要前端获取,需要通过expose_headers参数暴露这些头信息:
from flask import Flask from flask_cors import CORS app = Flask(__name__) # 暴露自定义响应头X-Total-Count CORS(app, expose_headers=['X-Total-Count'])
常见问题排查
配置完成后如果跨域请求仍然失败,可以从以下几个方面排查:
- 检查
origins配置是否包含前端实际的请求来源,注意端口号也需要匹配 - 开启凭证支持时,确认
origins没有使用通配符* - 检查预检请求的响应是否正确,预检请求的方法是OPTIONS,需要确保该请求没有被其他拦截器拦截
- 确认前端请求的Content-Type是否为允许的类型,比如自定义Content-Type可能需要额外配置
allow_headers
通过以上配置和优化,既可以解决Flask服务的跨域问题,又能最大程度降低跨域带来的安全风险,满足生产环境的使用要求。