Skip to content

跨域资源共享(CORS) ​

CORS 跨域

CORS(Cross-Origin Resource Sharing)跨域资源共享是前后端分离架构必须处理的问题。项目通过 flask-cors 扩展实现 CORS 支持,配置入口在 src/app.py 的 create_app() 中,通过 CORS_ALLOWED_ORIGINS 环境变量配置允许的跨域源。

配置项 ​

环境变量默认值说明
CORS_ALLOWED_ORIGINShttp://localhost:8001允许的跨域源(逗号分隔),留空则允许所有源
PROXY_NUM0可信代理层数。0 = 不信任 X-Forwarded-For;部署在 Nginx 后设为 1

实现原理 ​

CORS 配置位于 src/app.py 的 create_app() 中:

python
# src/app.py
from flask_cors import CORS
from config import CORS_ALLOWED_ORIGINS

# ============================================================
# 跨域资源共享配置
# ============================================================
if CORS_ALLOWED_ORIGINS:
    allowed_origins = [origin.strip() for origin in CORS_ALLOWED_ORIGINS.split(',') if origin.strip()]
    CORS(
        app,
        resources={r"/*": {"origins": allowed_origins}},
        supports_credentials=True
    )
else:
    CORS(
        app,
        resources={r"/*": {"origins": "*"}},
        supports_credentials=False
    )
  • 配置了 CORS_ALLOWED_ORIGINS 时:仅允许指定源,支持携带凭证(Cookie 等)
  • 未配置时:允许所有源,但不携带凭证

配置示例 ​

bash
# .env

# 开发环境:允许前端开发服务器
CORS_ALLOWED_ORIGINS=http://localhost:8001

# 生产环境:允许指定域名(多个用逗号分隔)
CORS_ALLOWED_ORIGINS=https://admin.example.com,https://www.example.com

生产环境

生产环境务必配置 CORS_ALLOWED_ORIGINS 为具体域名,避免允许所有源带来的安全风险。

可信代理配置 ​

当应用部署在 Nginx 等反向代理后,需要配置代理信任以获取真实客户端 IP:

python
# src/app.py
from werkzeug.middleware.proxy_fix import ProxyFix

# ============================================================
# 可信代理配置(反向代理环境下获取真实客户端IP)
# ============================================================
proxy_num = int(os.getenv('PROXY_NUM', 0))
if proxy_num > 0:
    app.wsgi_app = ProxyFix(app.wsgi_app, x_for=proxy_num, x_proto=proxy_num)

PROXY_NUM 说明:

值说明
0不信任 X-Forwarded-For,使用 request.remote_addr
1信任一层反向代理(如 Nginx)
2信任两层代理

安全提示

仅当应用部署在反向代理后才设置 PROXY_NUM>=1。如果应用被直接暴露(如 Docker bridge 映射端口),设置代理信任会导致客户端伪造 XFF 绕过安全校验。

中间件注册顺序 ​

CORS 在 src/app.py 中最先注册,确保所有响应都带 CORS 头:

python
# src/app.py - create_app() 中间件注册顺序
# 1. CORS 配置(最先注册→最外层)
# 2. ProxyFix 可信代理
# 3. register_operation_log(app)   # 操作日志
# 4. register_transaction(app)     # AOP 事务
# 5. register_v1(app)              # 路由注册
# 6. register_extends(app)         # 扩展初始化
# 7. register_middleware(app)      # 认证中间件
# 8. register_error_handlers(app)  # 异常处理

中间件执行顺序(从外到内):

CORS → 操作日志 → AOP 事务 → 认证 → 路由 → 业务逻辑

Flask-CORS 配置选项 ​

python
from flask_cors import CORS

CORS(app,
    origins=["https://admin.example.com"],  # 允许的源
    methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],  # 允许的方法
    allow_headers=["Content-Type", "Authorization"],  # 允许的头
    supports_credentials=True,  # 允许携带凭证
    max_age=3600,  # 预检请求缓存时间(秒)
)
参数说明默认值
origins允许的源*
methods允许的方法GET, HEAD, POST, OPTIONS
allow_headers允许的头*
supports_credentials允许携带凭证False
max_age预检请求缓存时间None

常见问题 ​

  • 跨域请求被拒绝
1. 检查 .env 中 CORS_ALLOWED_ORIGINS 是否包含前端地址
2. 检查前端请求的 Origin 头是否与配置一致
3. 生产环境检查 Nginx 是否正确传递 Origin 头
  • 携带凭证(Cookie)失败
1. CORS_ALLOWED_ORIGINS 必须配置具体域名,不能用 *
2. 前端请求需设置 withCredentials: true
3. 确保 supports_credentials=True

总结 ​

CORS 跨域配置通过 flask-cors 扩展在 src/app.py 中实现,通过 CORS_ALLOWED_ORIGINS 环境变量灵活配置允许的源。开发环境允许前端开发服务器(http://localhost:8001),生产环境应配置具体域名。反向代理场景通过 PROXY_NUM 配置代理信任层数,确保获取真实客户端 IP。

小蚂蚁云团队 · 提供技术支持