nginx

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > nginx > nginx跨域访问配置

nginx跨域访问配置的几种方法实现

作者:猩火燎猿

本文详细介绍了Nginx跨域配置方法,包括基本配置、只允许指定域名、携带Cookie的跨域、动态设置允许的Origin、支持不同路径的跨域控制、静态资源跨域以及根据请求方法细分CORS策略,感兴趣的可以了解一下

一、基本跨域配置

在 nginx 的 location 块中添加以下内容:

location /api/ {
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
    add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' always;
 
    # 处理预检请求(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;
}

说明:

二、只允许指定域名跨域

如果只允许某个域(如 https://www.example.com)跨域:

add_header 'Access-Control-Allow-Origin' 'https://www.example.com' always; 

三、完整示例

假设你有一个前端(端口 8080)和后端(端口 8000),nginx 代理 /api/ 到后端:

server {
    listen 80;
    server_name your.domain.com;
 
    location /api/ {
        proxy_pass http://127.0.0.1:8000;
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
        add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' 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;
        }
    }
}

四、配置后重载 nginx

每次修改配置后,记得重载 nginx:

nginx -s reload 

五、注意事项

六、支持携带 Cookie 的跨域配置

如果你需要前端跨域请求时携带 cookie(如登录态),CORS 需要特殊配置:

  1. Access-Control-Allow-Origin 不能为 *,必须指定具体的域名。
  2. 需要加上 Access-Control-Allow-Credentials: true

示例:

location /api/ {
    proxy_pass http://127.0.0.1:8000;
 
    add_header 'Access-Control-Allow-Origin' 'https://www.example.com' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
    add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' 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;
    }
}

前端请求时需要设置:

fetch('https://api.example.com/api/', {
  credentials: 'include', // 允许携带 cookie
  // 其他参数
})

七、根据请求头动态设置允许的 Origin

有时你希望根据请求头 Origin 动态设置允许的域名,可以用 nginx 的变量:

location /api/ {
    proxy_pass http://127.0.0.1:8000;
 
    if ($http_origin ~* "^https://(www\.example\.com|other\.domain\.com)$") {
        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, PUT, DELETE' always;
    add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' 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;
    }
}

八、常见问题排查

  1. add_header 不生效?

    • 确认 always 关键字已加上。
    • 确认没有被其他配置覆盖。
    • 确认 location 块没有被其他 server/location 块覆盖。
  2. OPTIONS 请求未返回 204?

    • 检查 if 语句是否正确。
    • 检查是否被后端拦截。
  3. 前端报错:CORS header ‘Access-Control-Allow-Origin’ missing?

    • 检查响应头是否包含该字段。
    • 用浏览器开发者工具 Network 检查响应头。
  4. 携带 cookie 时跨域失败?

    • 确认 Access-Control-Allow-Origin 不是 *,而是具体域名。
    • 确认 Access-Control-Allow-Credentials: true 已设置。
    • 前端 fetch/axios 需配置 credentials。

九、nginx 跨域配置模板(推荐)

可以将以下内容作为通用模板:

location /api/ {
    proxy_pass http://backend-server;
 
    # 支持跨域
    set $cors '';
    if ($http_origin ~* '^https://(www\.example\.com|other\.domain\.com)$') {
        set $cors 'true';
    }
 
    if ($cors = 'true') {
        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, PUT, DELETE' always;
    add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' 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;
    }
}

十、针对不同路径/接口做跨域控制

有时你只希望对部分接口(如 /api/)开放跨域,对其他接口(如 /admin/)不开放,可以这样配置:

server {
    listen 80;
    server_name your.domain.com;
 
    # 只对 /api/ 开放跨域
    location /api/ {
        proxy_pass http://backend-api;
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
        add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' 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;
        }
    }
 
    # /admin/ 不开放跨域
    location /admin/ {
        proxy_pass http://backend-admin;
        # 不添加跨域相关 header
    }
}

十一、静态资源跨域(如图片、字体、JS/CSS)

如果你希望静态资源(如图片、字体文件等)可以被其他域引用,需为静态资源 location 添加 CORS 响应头:

location /static/ {
    root /var/www/html;
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept' always;
}

注意:如果你希望字体文件可被第三方引用,必须加上 Access-Control-Allow-Origin,否则会有跨域问题。

十二、根据请求方法细分 CORS 策略

有时你希望 GET/POST/PUT/DELETE 允许跨域,而 PATCH 不允许,可以这样写:

location /api/ {
    proxy_pass http://backend-server;
 
    if ($request_method ~* "GET|POST|PUT|DELETE|OPTIONS") {
        add_header 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
        add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' 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;
    }
}

十三、反向代理多后端的跨域配置

如果 nginx 代理多个后端(如 /api1//api2/),每个后端都需要跨域:

location /api1/ {
    proxy_pass http://backend1;
    add_header 'Access-Control-Allow-Origin' '*' always;
    # ...同上
}
 
location /api2/ {
    proxy_pass http://backend2;
    add_header 'Access-Control-Allow-Origin' '*' always;
    # ...同上
}

十四、nginx 1.7.5 及以上版本的 always 参数

确保你用的 nginx 版本支持 always 参数,否则有些 header 在 4xx/5xx 状态下不会返回。

十五、安全建议

  1. 生产环境不要使用 *,要指定具体域名。
  2. 不建议在 / 根路径全局添加 CORS,容易引发安全隐患。
  3. 如需支持多域名跨域,推荐用变量和正则动态判断。
  4. 如果接口涉及敏感数据,务必开启认证和 HTTPS。

十六、调试技巧

十七、完整多场景配置模板

server {
    listen 80;
    server_name your.domain.com;
 
    # 静态资源
    location /static/ {
        root /var/www/html;
        add_header 'Access-Control-Allow-Origin' '*' always;
    }
 
    # API1 跨域
    location /api1/ {
        proxy_pass http://backend1;
        add_header 'Access-Control-Allow-Origin' 'https://www.a.com' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
        add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' 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;
        }
    }
 
    # API2 跨域
    location /api2/ {
        proxy_pass http://backend2;
        add_header 'Access-Control-Allow-Origin' 'https://www.b.com' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
        add_header 'Access-Control-Allow-Headers' 'Origin, Content-Type, Accept, Authorization' 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;
        }
    }
}

到此这篇关于nginx跨域访问配置的几种方法实现的文章就介绍到这了,更多相关nginx跨域访问配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文