跨域问题(CORS, Cross-Origin Resource Sharing)是浏览器出于安全考虑实施的同源策略限制。当Web应用尝试从不同域名、协议或端口请求资源时,浏览器会阻止这些请求。
Nginx可以作为反向代理服务器,将跨域请求转换为同源请求,从而绕过浏览器的限制。
server {
listen 80;
server_name yourdomain.com;
location /api/ {
# 代理到实际的后端服务器
proxy_pass http://backend-server:8080/;
# 处理跨域相关头信息
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
# 预检请求(OPTIONS)处理
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-server:8080/;
/
正确处理URI重写add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
Access-Control-Allow-Origin
: 允许的源,*
表示所有,生产环境建议指定具体域名Access-Control-Allow-Methods
: 允许的HTTP方法Access-Control-Allow-Headers
: 允许的请求头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;
}
Access-Control-Max-Age
指定预检请求的缓存时间(秒)proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
Authorization
等敏感头map $http_origin $cors_origin {
default "";
"~^https://domain1.com" "https://domain1.com";
"~^https://domain2.com" "https://domain2.com";
}
server {
# ...
add_header 'Access-Control-Allow-Origin' $cors_origin;
# ...
}
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Origin' $http_origin;
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin
不能为*
,必须指定具体域名location /ws/ {
proxy_pass http://backend-ws-server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
确保添加以下配置:
proxy_pass_request_headers on;
显式传递需要的头:
proxy_set_header Authorization $http_authorization;
使用more_set_headers
模块(需要安装headers-more模块):
more_set_headers 'Access-Control-Allow-Origin: $http_origin';
调整缓冲区大小:
client_max_body_size 100M;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
server {
listen 80;
server_name api.yourdomain.com;
# 全局CORS设置
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
add_header 'Access-Control-Expose-Headers' 'Content-Length, Content-Range';
# API代理
location /api/ {
proxy_pass http://backend-server:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 动态设置允许的源
if ($http_origin ~* (https?://[^/]*\.yourdomain\.com(:[0-9]+)?$)) {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
}
# 预检请求处理
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;
}
}
# 静态文件服务
location / {
root /var/www/html;
try_files $uri $uri/ /index.html;
}
}
nginx -t
nginx -s reload
curl -I -X OPTIONS http://yourdomain.com/api/endpoint
Access-Control-Allow-Origin: *
通过以上配置,Nginx可以有效地解决跨域问题,同时确保请求头正确传递到后端服务。根据实际需求调整配置参数,平衡功能与安全性。