当你的网站(比如 https://a.com)想要请求另一个不同域名下的资源时(比如 API 服务器 https://api.b.com),浏览器出于安全考虑,会默认阻止这次请求。
在 Nginx 中配置 CORS,就等于在服务器的大门口给这个请求盖上一个“允许通行”的章。
一、为什么需要配置 CORS?
简单来说,就是为了解决“跨域资源共享”的问题。最常见的场景:
- 前后端分离:前端项目部署在
https://www.your-domain.com,后端 API 服务部署在https://api.your-domain.com。 - 调用外部 API:你的网站需要直接从浏览器请求第三方提供的 API 资源。
如果没有 CORS 配置,浏览器控制台就会无情地抛出类似这样的错误:Access to XMLHttpRequest at '…' from origin '…' has been blocked by CORS policy…
二、核心配置指令
在 Nginx 中,我们主要使用 add_header 指令来添加 CORS 相关的 HTTP 响应头。
| 响应头 | 说明 | 示例 |
|---|---|---|
Access-Control-Allow-Origin | (最重要!) 允许哪个源(域名)可以访问我。 | * (允许任何域名,慎选!) https://www.a.com (只允许 https://www.a.com) |
Access-Control-Allow-Methods | 允许的 HTTP 请求方法。 | GET, POST, PUT, DELETE, OPTIONS |
Access-Control-Allow-Headers | 允许的自定义请求头。 | Content-Type, Authorization, X-Requested-With |
Access-Control-Allow-Credentials | 是否允许发送 Cookie。 | true (注意:当为 true 时, Access-Control-Allow-Methods不能为 *) |
三、什么是“预检”请求 (Preflight)?
对于一些“非简单请求”(比如 PUT、 DELETE 请求,或者带了自定义请求头的 POST 请求),浏览器会先发送一个 OPTIONS 方法的“预检”请求,来问问服务器:“我待会儿要用这个姿势(方法和请求头)请求你,你支持吗?”
服务器需要正确响应这个 OPTIONS 请求,告诉浏览器“我支持”,然后浏览器才会发送真正的请求。所以,我们的 Nginx 配置必须能处理这种 OPTIONS 请求。
注意:只要是跨域请求,就需要配置 CORS 相关 header,跨域请求又分简单请求和非简单请求,非简单请求才会在正式请求之前发送预检请求
四、配置示例
下面是一个非常实用且考虑了安全性和预检请求的配置。你可以把它放在 Nginx 配置文件(如 nginx.conf 或 sites-available/your-site)的 server 或 location 块中。
# 将此段配置放在你的 server 或 location 块中
# 例如: location /api/ { ... }
# ---------------- CORS 配置开始 ----------------
# 1. 设置允许跨域的源 (域名)
# 为了安全,强烈建议指定你的前端域名,而不是使用 "*"
add_header 'Access-Control-Allow-Origin' "https://www.your-frontend.com" always;
# 2. 设置允许的请求方法
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
# 3. 设置允许的请求头
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
# 4. 设置是否允许携带 Cookie
# 如果你的前端需要传递 cookie, 请设置为 true
# 注意: 当 Access-Control-Allow-Origin 不是 "*" 时,这个才生效
add_header 'Access-Control-Allow-Credentials' 'true' always;
# 5. 处理 "预检" (Preflight) 请求
# 当请求方法为 OPTIONS 时,直接返回 204 (No Content),表示预检成功
# 浏览器收到 204 后,才会发送真正的业务请求
if ($request_method = 'OPTIONS') {
# 预检请求的有效期,单位秒。在此期间,浏览器无需为同一请求再次发送预检。
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
# ---------------- CORS 配置结束 ----------------
# 你原来的其他配置,比如 proxy_pass
# proxy_pass http://backend_server;
示例说明:
- 处理预检请求:通过
if ($request_method = 'OPTIONS')判断,如果是预检请求,就直接返回204状态码,并附上 CORS 相关的头信息,然后中断请求,不再转发给后端服务。这样可以减轻后端服务的压力。 always参数:在add_header指令的末尾加上always是个好习惯,它可以确保无论响应状态码是什么(比如 404, 500),这些 CORS 头部都会被添加,从而给前端更明确的调试信息。
五、如何使用?
- 找到你的网站对应的 Nginx 配置文件。
- 将上述配置示例代码块复制到合适的
server { ... }或location / { ... }中。 - 修改域名!将
www.your-frontend.com替换成你自己的前端应用域名。 - 检查 Nginx 配置语法是否正确:
sudo nginx -t - 重新加载 Nginx 配置使其生效:
sudo nginx -s reload
现在,你的 Nginx 已经成功配置好 CORS,可以愉快地进行跨域请求了!