Nginx 跨域配置中add_header 和 proxy_set_header區(qū)別
做前端開(kāi)發(fā)的同學(xué),幾乎都踩過(guò)跨域的坑; 做后端或運(yùn)維的同學(xué),大概率也寫過(guò) Nginx 跨域配置。
但很多人配置時(shí)都會(huì)有個(gè)疑問(wèn):
“為什么我加了 Access-Control-Allow-Origin,瀏覽器還是報(bào)跨域?” “add_header 和 proxy_set_header 到底哪個(gè)才是加跨域頭的?”
甚至有人誤以為“跨域頭要轉(zhuǎn)發(fā)給后端”,結(jié)果白白走了很多彎路。
今天,我們就從這兩個(gè)核心指令的區(qū)別入手,徹底講清楚 Nginx 如何正確處理跨域,并附上一套開(kāi)箱即用的配置模板。
一、核心問(wèn)題:跨域頭該用add_header還是proxy_set_header?
這是最容易混淆的點(diǎn)。先說(shuō)結(jié)論:
? 處理瀏覽器跨域,只用 add_header! ? proxy_set_header 是用來(lái)給后端傳請(qǐng)求信息的,和跨域校驗(yàn)本身無(wú)關(guān)。
很多人踩坑,就是因?yàn)榘堰@兩個(gè)指令的作用對(duì)象搞反了。我們用一張表徹底分清:
| 指令 | 作用對(duì)象 | 核心目的 | 是否用于跨域校驗(yàn) |
|---|---|---|---|
| add_header | Nginx → 瀏覽器(響應(yīng)頭) | nginx返回給瀏覽器的響應(yīng)添加頭信息,相當(dāng)于nginx幫后端接口補(bǔ)充了header信息 | ? 是!跨域頭必須用它加 |
| proxy_set_header | Nginx → 后端(請(qǐng)求頭) | 給轉(zhuǎn)發(fā)到后端的請(qǐng)求添加頭信息 | ? 否!僅用于傳遞請(qǐng)求上下文(如真實(shí) IP) |
一句話總結(jié):
瀏覽器跨域校驗(yàn),只看“最終收到的響應(yīng)頭”里有沒(méi)有 Access-Control-\* 字段。 而 add_header 就是專門負(fù)責(zé)往響應(yīng)頭里加這些字段的; proxy_set_header 加的是請(qǐng)求頭,瀏覽器根本看不到,自然對(duì)跨域無(wú)效。
二、跨域的本質(zhì):是瀏覽器的安全機(jī)制,與后端無(wú)關(guān)
在講配置前,先明確一個(gè)關(guān)鍵認(rèn)知:
?? 跨域是瀏覽器的行為,不是后端的行為。
舉個(gè)例子: 前端 http://localhost:8080 請(qǐng)求后端 http://localhost:59200,因端口不同,屬于跨域。
這個(gè)過(guò)程中:
- 后端其實(shí)已經(jīng)正常處理了請(qǐng)求并返回了數(shù)據(jù);
- 但瀏覽器會(huì)攔截這份響應(yīng),檢查其中是否包含允許 http://localhost:8080 訪問(wèn)的聲明;
- 如果有,就把數(shù)據(jù)交給前端;如果沒(méi)有,就拋出跨域錯(cuò)誤。
所以,解決跨域的核心,就是讓瀏覽器收到的響應(yīng)頭中包含合法的 Access-Control-\* 字段。
而 Nginx 的作用,就是在后端未配置這些字段時(shí),替后端“補(bǔ)上”,讓瀏覽器放行。
三、Nginx 跨域配置實(shí)操:模板 + 逐行解析
下面是一套生產(chǎn)可用的 Nginx 跨域配置模板,先看代碼,再逐行拆解:
location / {
# 1. 跨域核心響應(yīng)頭(給瀏覽器看的)
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. 預(yù)檢請(qǐng)求直接處理,不轉(zhuǎn)發(fā)給后端
if ($request_method = 'OPTIONS') {
return 204;
}
# 3. 反向代理配置(給后端傳請(qǐng)求信息)
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指令詳解
這部分是解決跨域的關(guān)鍵,每行都有明確作用,且必須帶 always:
- Access-Control-Allow-Origin:指定允許訪問(wèn)的前端域名。
- 填具體地址(如 'http://localhost:8080')最安全;
- 若填 '*',則不能攜帶憑證(如 Cookie、Authorization),否則瀏覽器會(huì)拒絕。
- Access-Control-Allow-Methods:列出前端可能使用的 HTTP 方法(如 GET/POST/PUT 等)。
- Access-Control-Allow-Headers:聲明允許的自定義請(qǐng)求頭(如 Content-Type、Authorization)。
- always 關(guān)鍵字: ?? 極其重要! 它確保即使后端返回 404、500 等非 2xx 響應(yīng),跨域頭依然會(huì)被添加。 如果省略 always,錯(cuò)誤響應(yīng)將沒(méi)有跨域頭,瀏覽器照樣攔截——這是最常見(jiàn)的“配了卻無(wú)效”的原因!
2. 為什么要單獨(dú)處理OPTIONS預(yù)檢請(qǐng)求?
對(duì)于 POST、PUT 等“非簡(jiǎn)單請(qǐng)求”,瀏覽器會(huì)先發(fā)一個(gè) OPTIONS 預(yù)檢請(qǐng)求,詢問(wèn)服務(wù)器:“你允許我這么請(qǐng)求嗎?”
如果 Nginx 不處理,這個(gè) OPTIONS 會(huì)被轉(zhuǎn)發(fā)給后端。而很多后端服務(wù)根本沒(méi)有實(shí)現(xiàn) OPTIONS 接口,直接返回 404 或 500,導(dǎo)致預(yù)檢失敗。
因此,我們用:
if ($request_method = 'OPTIONS') {
return 204;
}
讓 Nginx 直接返回 204(No Content),高效通過(guò)預(yù)檢,避免打擾后端。
3.proxy_set_header的真實(shí)作用
這部分和跨域無(wú)關(guān),純粹是為了讓后端拿到正確的請(qǐng)求上下文:
- proxy_pass:將請(qǐng)求轉(zhuǎn)發(fā)到后端服務(wù);
- proxy_set_header Host $host:傳遞原始 Host,避免后端路由出錯(cuò);
- X-Real-IP / X-Forwarded-For:傳遞客戶端真實(shí) IP,方便日志記錄或風(fēng)控。
?? 再?gòu)?qiáng)調(diào)一次:這些頭是給后端看的,瀏覽器完全不關(guān)心。
4. 完整請(qǐng)求流程圖解
結(jié)合上述配置,一次跨域請(qǐng)求的完整流程如下:
- 瀏覽器發(fā)送 OPTIONS 預(yù)檢請(qǐng)求 → 到達(dá) Nginx;
- Nginx 匹配 location /,觸發(fā) OPTIONS 處理邏輯,直接返回 204 + 跨域頭;
- 瀏覽器校驗(yàn)通過(guò),發(fā)送真實(shí)請(qǐng)求(如 POST)→ 到達(dá) Nginx;
- Nginx 通過(guò) proxy_set_header 補(bǔ)充 Host/IP 等信息,轉(zhuǎn)發(fā)給后端;
- 后端處理并返回業(yè)務(wù)響應(yīng)(可能不含跨域頭);
- Nginx 接收響應(yīng),通過(guò) add_header 添加跨域頭,再返回給瀏覽器;
- 瀏覽器驗(yàn)證響應(yīng)頭合規(guī),將數(shù)據(jù)交給前端 JavaScript —— 跨域成功!
四、常見(jiàn)踩坑點(diǎn) & 避坑指南
? 坑 1:加了跨域頭還是報(bào)錯(cuò)?→ 忘了always
解決方案:所有 add_header 跨域指令必須加上 always。
? 坑 2:用proxy_set_header加跨域頭
錯(cuò)誤示例:proxy_set_header Access-Control-Allow-Origin *; 后果:跨域頭被加到請(qǐng)求頭里,瀏覽器看不到,完全無(wú)效。
? 坑 3:Allow-Origin: *+ 攜帶Authorization
問(wèn)題:瀏覽器禁止 * 與憑證(credentials)共存。 正確做法:必須指定具體前端域名,如 'http://localhost:8080'。
? 坑 4:跨域頭配在server塊,不在location塊
原因:Nginx 中 add_header 不會(huì)繼承上級(jí)塊的配置。 正確位置:務(wù)必放在實(shí)際匹配請(qǐng)求的 location 塊內(nèi)。
五、總結(jié)
Nginx 處理跨域的核心邏輯其實(shí)很簡(jiǎn)單:
- ? 用
add_header給響應(yīng)頭添加跨域字段,讓瀏覽器放行; - ? 用
proxy_set_header給請(qǐng)求頭補(bǔ)充上下文,讓后端正常工作。
記?。?/p>
跨域是瀏覽器的安全策略,后端可以完全不知情。 Nginx 充當(dāng)“中間人”,既幫后端屏蔽了跨域細(xì)節(jié),又幫前端拿到了數(shù)據(jù)。
把上面的配置模板稍作修改(替換你的前端地址和后端地址),就能解決99% 的跨域場(chǎng)景。
到此這篇關(guān)于Nginx 跨域配置中add_header 和 proxy_set_header區(qū)別的文章就介紹到這了,更多相關(guān)Nginx add_header 和 proxy_set_header內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nginx+SpringBoot實(shí)現(xiàn)負(fù)載均衡的示例
這篇文章主要介紹了Nginx優(yōu)雅的實(shí)現(xiàn)負(fù)載均衡,幫助大家更好的理解和使用nginx,感興趣的朋友可以了解下2020-10-10
Forever+nginx部署Node站點(diǎn)的方法示例
這篇文章主要介紹了Forever+nginx部署Node站點(diǎn)的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
解決nginx“504?Gateway?Time-out”錯(cuò)誤
這篇文章介紹了解決nginx“504?Gateway?Time-out”錯(cuò)誤的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12
詳解Nginx 被動(dòng)檢查服務(wù)器的存活狀態(tài)
Nginx 可以持續(xù)測(cè)試您的上游服務(wù)器,避免出現(xiàn)故障的服務(wù)器,并將恢復(fù)的服務(wù)器優(yōu)雅地添加到負(fù)載均衡組中。這篇文章主要介紹了Nginx 被動(dòng)檢查服務(wù)器的存活狀態(tài),需要的朋友可以參考下2021-10-10
Apache和Nginx實(shí)現(xiàn)虛擬主機(jī)的3種方式小結(jié)
Apache是一個(gè)模型化的服務(wù)器,可以運(yùn)行在幾乎所有的服務(wù)器上。其屬于應(yīng)用服務(wù)器,這篇文章主要介紹了Apache和Nginx實(shí)現(xiàn)虛擬主機(jī)的3種方式,需要的朋友可以參考下2023-11-11
nginx配置域名(ssl和非ssl形式)的實(shí)現(xiàn)示例
本文主要介紹了nginx配置域名(ssl和非ssl形式)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-07-07
nginx用正則表達(dá)式實(shí)現(xiàn)泛域名自動(dòng)匹配目錄的方法
這篇文章主要介紹了nginx用正則表達(dá)式實(shí)現(xiàn)泛域名自動(dòng)匹配目錄的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05

