nginx配置允许跨域白名单V2

1.核心判断逻辑

为了避免代码冗余,可以把这套判断逻辑写成一个独立的文件(例如 cors_check.conf),然后在需要的 location 里 include 它:
文件:conf.d/cors_check.conf

# --- 跨域精准拦截逻辑 ---
set $cors_check "";

# 步骤A: 检查是否存在 Origin 头部(判断是否为跨域)
if ($http_origin != "") {
    set $cors_check "is_cors";
}

# 步骤B: 检查是否不在白名单内 ($allow_cors 来自外层的 map 定义)
if ($allow_cors = 0) {
    set $cors_check "${cors_check}_deny";
}

# 步骤C: 只有跨域且不在白名单时,返回带说明的 403
if ($cors_check = "is_cors_deny") {
    add_header 'Content-Type' 'application/json; charset=utf-8';
    # 返回详细 JSON,方便前端定位问题
    return 403 '{"status": 403, "error": "CORS_POLICY_BLOCKED", "reason": "Nginx: The origin [$http_origin] is not in the whitelist.", "suggestion": "Please contact OPS to add this domain to the allow-list."}';
}

2.项目中的完整应用示例

nginx.conf中,按照以下结构组织代码:

# 【第一步:全局白名单定义】
http {
    # --- map 必须在这里,定义在所有 server 之前 ---
map $http_origin $allow_cors {
    default 0;
    "https://zbc.cn"           1;
    "https://abc" 1;
    "http://192.168.1.85:8080"             1;
    # ... 其他白名单
}
server {
    listen 80;
    server_name your-project.com;

    # 【第二步:应用到具体的 Location】
    location /prod-api {
        # 引入刚才创建的拦截逻辑
        include conf.d/cors_check.conf;

        # 如果通过了拦截,处理 OPTIONS 预检请求(可选但推荐)
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' $http_origin always;
            add_header 'Access-Control-Allow-Credentials' 'true' always;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
            add_header 'Access-Control-Allow-Headers' '*' always;
            return 204;
        }
        # 1. 如果后端有配置*则隐藏后端发出的跨域头(防止冲突)
        proxy_hide_header 'Access-Control-Allow-Origin';
        proxy_hide_header 'Access-Control-Allow-Credentials';
        proxy_hide_header 'Access-Control-Allow-Methods';
        proxy_hide_header 'Access-Control-Allow-Headers';

        # 业务转发
        proxy_pass http://192.168.98.100:8301;

        # 成功通过后,必须给响应补上跨域头,否则浏览器还是会拦截
        add_header 'Access-Control-Allow-Origin' $http_origin always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' '*' always;
    }
}
}

说明

1.错误隔离:如果是因为目录权限、IP黑名单导致的 403,会返回 Nginx 默认的错误页;只有因为 Origin 不在白名单 导致的 403,才会返回那段 JSON 提示。

2.自助诊断:JSON 信息里直接输出了 $http_origin。当开发人员找你时,你只需要问他:“报错信息里的 origin 是哪个?” 就能立刻判断是没配、还是协议(http/https)配错了。

3.标准化:通过 include 方式,你以后在其他 location 甚至其他 server 块里,只需要一行代码就能复用这套逻辑。

posted @ 2026-02-05 15:27  开心burukku  阅读(8)  评论(0)    收藏  举报