跨域的坑 - nginx配置项的always参数
·
一、简介
跨域(CORS, Cross-Origin Resource Sharing)是浏览器出于安全策略(同源策略)限制,阻止一个源(origin)的网页向另一个源发起某些请求的行为。
🔒 什么是“同源”?
协议(scheme)+ 域名(host)+ 端口(port)三者完全一致才算同源。
例如:
https://api.example.com:443 和 https://www.example.com:443 → 不同源(域名不同)
http://localhost:3000 和 http://localhost:8080 → 不同源(端口不同)
🌐 跨域请求的两种类型
- 简单请求(Simple Request)
- 满足以下条件:
方法:GET、POST、HEAD
头部仅限:Accept、Accept-Language、Content-Language、Content-Type(且值只能是 application/x-www-form-urlencoded、multipart/form-data、text/plain)
无自定义头部(如 Authorization、X-Token 等)
✅ 浏览器直接发送请求,但会检查响应头是否允许跨域。
- 满足以下条件:
- 预检请求(Preflight Request)
- 不满足上述条件时,浏览器先发一个 OPTIONS 请求询问服务器:“你允许这个跨域请求吗?”
只有预检通过,才发送真正的请求。
- 不满足上述条件时,浏览器先发一个 OPTIONS 请求询问服务器:“你允许这个跨域请求吗?”
二、后端如何解决跨域
核心:在响应中添加 CORS 相关 HTTP 头部
- 基础 CORS 响应头(Nginx / 应用层均可配置)
Access-Control-Allow-Origin: https://your-frontend.com
# 或 *(但不能用于带凭证的请求)
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
Access-Control-Allow-Credentials: true # 如果需要携带 Cookie
⚠️ 安全建议:生产环境不要用 *,应明确指定可信源。
- 在 Nginx 中统一处理(推荐)
location /api/ {
# 允许的源(可设为变量或具体域名)
add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,Content-Type,Authorization' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
# 处理预检请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 86400; # 预检结果缓存 24 小时
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain; charset=utf-8';
return 204;
}
# 代理到后端服务
proxy_pass http://backend;
}
✅ 使用 always 参数确保 4xx/5xx 错误响应也包含 CORS 头。
如果不设置always参数,以Access-Control-Allow-Origin为例。 Access-Control-Allow-Origin只在 2xx / 3xx 响应里出现;一旦后端返回 4xx / 5xx,这个头会被直接丢弃,浏览器仍然会报跨域被拦。
因此,如果接口可能返回 4xx / 5xx 且仍需跨域调试,就必须加上 always,否则 4xx / 5xx 响应会因为缺少该头而再次触发浏览器的 CORS 阻断。
- 在应用代码中处理
如:Django (Python)中,安装 django-cors-headers,配置:
CORS_ALLOWED_ORIGINS = ["https://your-frontend.com"]
CORS_ALLOW_CREDENTIALS = True
更多推荐


所有评论(0)