适用场景:Web服务器配置、API接口开发、静态资源托管
跨域(CORS)基础概念
什么是跨域?
浏览器出于安全考虑,禁止网页从一个域名(如 https://a.com
)请求另一个域名(如 https://b.com
)的资源。CORS(跨域资源共享)通过HTTP头字段允许服务器声明允许的源,解决跨域问题。
Nginx 配置方法
方法一:全局允许所有域名跨域
适用场景:开发环境快速测试(不推荐生产环境使用)。
配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| server { listen 80; server_name example.com;
location / { add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
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; }
proxy_pass http://backend; } }
|
配置说明
Access-Control-Allow-Origin
:允许跨域的域名,*
表示允许所有域名。Access-Control-Allow-Methods
:允许的 HTTP 方法(如 GET
、POST
等)。Access-Control-Allow-Headers
:允许的请求头。Access-Control-Expose-Headers
:允许客户端访问的响应头。Access-Control-Max-Age
:预检请求的缓存时间(单位:秒)。OPTIONS
请求:用于处理浏览器的预检请求(Preflight Request)。
方法二:允许特定域名跨域
适用场景:生产环境安全配置。
配置示例
如果只想允许特定域名跨域,可以将 Access-Control-Allow-Origin
设置为具体的域名:
1 2 3 4 5 6 7 8 9 10 11
| server { listen 80; server_name example.com;
location / { add_header 'Access-Control-Allow-Origin' 'https://client.example.com' always; } }
|
方法三:允许多个域名跨域
适用场景:需要支持多个可信域名。
配置示例
Nginx 原生不支持直接配置多个域名,但可以通过变量和条件判断实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| map $http_origin $cors_origin { default ''; "~^https://client1\.example\.com$" $http_origin; "~^https://client2\.example\.com$" $http_origin; }
server { listen 80; server_name example.com;
location / { add_header 'Access-Control-Allow-Origin' $cors_origin always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
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; }
proxy_pass http://backend; } }
|
方法四:静态文件跨域配置
适用场景:直接通过Nginx提供静态资源(如图片、文件)
配置示例
如果 Nginx 直接提供静态文件服务,可以在 location
块中添加跨域头:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| server { listen 80; server_name static.example.com;
location /static/ { add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
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; }
alias /path/to/static/files/; } }
|
注意事项
- 安全建议
- 避免生产环境使用
*
:可能导致安全漏洞,建议指定具体域名。 - HTTPS优先:跨域源建议使用HTTPS协议。
- 缓存问题
- 浏览器可能缓存预检请求结果,修改配置后需清理浏览器缓存。
- 代理配置兼容性
- 如果后端服务(如Node.js)已配置CORS,需确保Nginx与后端配置不冲突。
- 版本兼容性:Nginx 1.19+(支持
always
参数)
测试与验证
配置完成后,重启 Nginx 并测试跨域是否生效:
1 2
| sudo nginx -t sudo systemctl restart nginx
|
使用浏览器开发者工具或 curl
命令检查响应头:
1 2
| curl -I -H "Origin: https://client.example.com" http://example.com/api
|
确保响应头中包含 Access-Control-Allow-Origin
等相关字段。
扩展配置技巧
技巧1:动态设置CORS头
根据请求来源动态返回允许的域名:
1 2 3 4 5 6 7 8 9 10
| map $http_origin $allowed_origin { default ''; "~^(https?://)?.+\.example\.com$" $http_origin; }
location /api { add_header 'Access-Control-Allow-Origin' $allowed_origin always; }
|
技巧2:限制HTTP方法
仅允许安全的方法(如GET/POST):
1
| add_header 'Access-Control-Allow-Methods' 'GET, POST' always;
|