nginx

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > nginx > Nginx  add_header 和 proxy_set_header

Nginx 跨域配置中add_header 和 proxy_set_header区别

作者:小飞Coding

本文主要介绍了Nginx 跨域配置中add_header 和 proxy_set_header区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

做前端开发的同学,几乎都踩过跨域的坑; 做后端或运维的同学,大概率也写过 Nginx 跨域配置。

但很多人配置时都会有个疑问:

“为什么我加了 Access-Control-Allow-Origin,浏览器还是报跨域?” “add_header 和 proxy_set_header 到底哪个才是加跨域头的?”

甚至有人误以为“跨域头要转发给后端”,结果白白走了很多弯路。

今天,我们就从这两个核心指令的区别入手,彻底讲清楚 Nginx 如何正确处理跨域,并附上一套开箱即用的配置模板

一、核心问题:跨域头该用add_header还是proxy_set_header?

这是最容易混淆的点。先说结论:

✅ 处理浏览器跨域,只用 add_header! ❌ proxy_set_header 是用来给后端传请求信息的,和跨域校验本身无关。

很多人踩坑,就是因为把这两个指令的作用对象搞反了。我们用一张表彻底分清:

指令作用对象核心目的是否用于跨域校验
add_headerNginx → 浏览器(响应头)nginx返回给浏览器的响应添加头信息,相当于nginx帮后端接口补充了header信息✅ 是!跨域头必须用它加
proxy_set_headerNginx → 后端(请求头)给转发到后端的请求添加头信息❌ 否!仅用于传递请求上下文(如真实 IP)

一句话总结:

浏览器跨域校验,只看“最终收到的响应头”里有没有 Access-Control-\* 字段。 而 add_header 就是专门负责往响应头里加这些字段的; proxy_set_header 加的是请求头,浏览器根本看不到,自然对跨域无效。

二、跨域的本质:是浏览器的安全机制,与后端无关

在讲配置前,先明确一个关键认知:

🔒 跨域是浏览器的行为,不是后端的行为。

举个例子: 前端 http://localhost:8080 请求后端 http://localhost:59200,因端口不同,属于跨域。

这个过程中:

所以,解决跨域的核心,就是让浏览器收到的响应头中包含合法的 Access-Control-\* 字段。

而 Nginx 的作用,就是在后端未配置这些字段时,替后端“补上”,让浏览器放行。

三、Nginx 跨域配置实操:模板 + 逐行解析

下面是一套生产可用的 Nginx 跨域配置模板,先看代码,再逐行拆解:

location / {
    # 1. 跨域核心响应头(给浏览器看的)
    add_header 'Access-Control-Allow-Origin' 'http://localhost:8080' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;

    # 2. 预检请求直接处理,不转发给后端
    if ($request_method = 'OPTIONS') {
        return 204;
    }

    # 3. 反向代理配置(给后端传请求信息)
    proxy_pass http://localhost:59200;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

1. 跨域核心:add_header指令详解

这部分是解决跨域的关键,每行都有明确作用,且必须带 always

2. 为什么要单独处理OPTIONS预检请求?

对于 POST、PUT 等“非简单请求”,浏览器会先发一个 OPTIONS 预检请求,询问服务器:“你允许我这么请求吗?”

如果 Nginx 不处理,这个 OPTIONS 会被转发给后端。而很多后端服务根本没有实现 OPTIONS 接口,直接返回 404 或 500,导致预检失败。

因此,我们用:

if ($request_method = 'OPTIONS') {
    return 204;
}

让 Nginx 直接返回 204(No Content),高效通过预检,避免打扰后端。

3.proxy_set_header的真实作用

这部分和跨域无关,纯粹是为了让后端拿到正确的请求上下文:

💡 再强调一次:这些头是给后端看的,浏览器完全不关心。

4. 完整请求流程图解

结合上述配置,一次跨域请求的完整流程如下:

  1. 浏览器发送 OPTIONS 预检请求 → 到达 Nginx;
  2. Nginx 匹配 location /,触发 OPTIONS 处理逻辑,直接返回 204 + 跨域头;
  3. 浏览器校验通过,发送真实请求(如 POST)→ 到达 Nginx;
  4. Nginx 通过 proxy_set_header 补充 Host/IP 等信息,转发给后端;
  5. 后端处理并返回业务响应(可能不含跨域头);
  6. Nginx 接收响应,通过 add_header 添加跨域头,再返回给浏览器;
  7. 浏览器验证响应头合规,将数据交给前端 JavaScript —— 跨域成功!

四、常见踩坑点 & 避坑指南

❌ 坑 1:加了跨域头还是报错?→ 忘了always

解决方案:所有 add_header 跨域指令必须加上 always。

❌ 坑 2:用proxy_set_header加跨域头

错误示例:proxy_set_header Access-Control-Allow-Origin *; 后果:跨域头被加到请求头里,浏览器看不到,完全无效。

❌ 坑 3:Allow-Origin: *+ 携带Authorization

问题:浏览器禁止 * 与凭证(credentials)共存。 正确做法:必须指定具体前端域名,如 'http://localhost:8080'。

❌ 坑 4:跨域头配在server块,不在location块

原因:Nginx 中 add_header 不会继承上级块的配置。 正确位置:务必放在实际匹配请求的 location 块内。

五、总结

Nginx 处理跨域的核心逻辑其实很简单:

记住:

跨域是浏览器的安全策略,后端可以完全不知情。 Nginx 充当“中间人”,既帮后端屏蔽了跨域细节,又帮前端拿到了数据。

把上面的配置模板稍作修改(替换你的前端地址和后端地址),就能解决99% 的跨域场景

到此这篇关于Nginx 跨域配置中add_header 和 proxy_set_header区别的文章就介绍到这了,更多相关Nginx  add_header 和 proxy_set_header内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

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