当我们想让 Nginx 支持多个域名跨域时,关键在于告诉 Nginx:“嘿,当这些特定域名来请求资源时,请给它们开绿灯!”
实现这个目标,我们主要利用 Nginx 的 map 指令和 $http_origin 变量。
$http_origin 能获取到请求来自哪个源(域名),而 map 则可以根据这个源,动态地设置 Access-Control-Allow-Origin 的值。
定义你的“白名单”域名
首先,我们需要在 Nginx 的 http 配置块中,创建一个“白名单”列表。这个列表里放的就是你允许跨域访问的那些域名。
http {
# ... 其他配置 ...
# 定义一个变量 $cors_origin,默认值为 0
map $http_origin $cors_origin {
default 0;
"http://www.a.com" 1;
"https://www.b.com" 1;
"http://localhost:8080" 1;
}
# ... 其他配置 ...
}
配置说明:
map $http_origin $cors_origin { ... }: 这就像建立一个对应关系。$http_origin是请求来的域名,$cors_origin是我们自定义的一个变量。default 0;: 如果请求的域名不在我们的白名单里,$cors_origin的值就是0。"http://www.a.com" 1;: 如果请求来自http://www.a.com,那么$cors_origin的值就是1。这里你可以添加任意多个你想要支持的域名。
在你的 server 配置中“智能”放行
接下来,在你需要处理跨域请求的 server 配置块中(通常是 location 块),我们要根据 $cors_origin 的值来决定是否给请求“盖章放行”。
server {
# ... 其他配置 ...
location / {
# 如果 $cors_origin 是 1,就把请求的源域名赋值给 $cors_origin
if ($cors_origin = '1') {
set $cors_origin $http_origin;
}
# 允许指定的域名访问
add_header Access-Control-Allow-Origin "$cors_origin";
# 允许携带 Cookie
add_header Access-Control-Allow-Credentials "true";
# 允许的请求方法
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
# 允许的请求头
add_header Access-Control-Allow-Headers "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range";
# 针对 OPTIONS 预检请求的处理
if ($request_method = 'OPTIONS') {
return 204;
}
}
# ... 其他配置 ...
}
配置说明:
if ($cors_origin = '1') { set $cors_origin $http_origin; }: 这是一个判断。如果$cors_origin的值是我们之前设定的1(意味着这个域名在白名单里),那么我们就把当前请求的域名($http_origin)赋值给$cors_origin变量。add_header Access-Control-Allow-Origin "$cors_origin";: 这就是最关键的一步!它会把处理后的$cors_origin变量的值(也就是白名单里的那个域名)添加到响应头里,告诉浏览器:“这个域名是自己人,可以访问!” 如果请求的域名不在白名单里,$cors_origin的值就是0,浏览器就会拒绝这个跨域请求。
重新加载 Nginx 配置
最后一步,别忘了让 Nginx 加载你最新的配置!
nginx -t # 检查配置语法是否正确
nginx -s reload # 重新加载配置
搞定!现在你的 Nginx 就可以愉快地支持多个域名跨域啦!