跨域CORS(Cross-Origin Resource Sharing)在哪端添加跨域许可配置?

问题本质是 CORS(Cross-Origin Resource Sharing)控制权在哪里?从协议层看:跨域一定是服务端(响应端)决定的,但可以由 Nginx 代替后端实现。

换句话说:

  • 浏览器负责拦截
  • 服务端负责授权
  • Nginx 可以充当服务端授权者

1.Nginx 统一处理(网关层)

让 Nginx 在响应阶段直接加 Header

1
2
3
4
5
6
7
8
9
10
11
12
location /api/ {
# allow cros
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";

if ($request_method = OPTIONS) {
return 204;
}

proxy_pass http://backend;
}

浏览器 → Nginx → 后端,CORS 在 Nginx 就被处理掉了

优点:

  • 所有服务统一
  • 后端无感
  • 性能好

缺点:

  • 复杂策略不好做

2.后端应用处理(应用层)

例如 Golang / Java / Python 在代码中返回 CORS 头。

浏览器请求:

Origin: https://a.com

后端返回:

Access-Control-Allow-Origin: https://a.com
Access-Control-Allow-Methods: GET,POST,PUT
Access-Control-Allow-Headers: Content-Type,Authorization

优点:

  • 控制粒度细
  • 可按用户 / API / token 控制
  • 可以动态返回 Origin

缺点:

  • 每个服务都要写
  • 微服务多了很麻烦

3.跨域处理阶段

跨域 不是请求阶段处理,而是响应阶段处理

浏览器逻辑:

浏览器
   │
   │ 1 发送请求 (带 Origin)
   ▼
服务器
   │
   │ 2 返回 Access-Control-Allow-Origin
   ▼
浏览器
   │
   │ 3 决定是否允许 JS 读取响应

4.预检请求(Preflight)

当请求是:

  • PUT
  • DELETE
  • PATCH
  • 自定义 Header
  • application/json

浏览器会先发一个:

OPTIONS /api/user

服务器必须返回:

Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers

否则 真实请求不会发送

所以 Nginx 一般要加:

1
2
3
if ($request_method = OPTIONS) {
return 204;
}