Nginx反向代理后端接口解決跨域沖突、預(yù)檢報(bào)錯(cuò)問(wèn)題全流程
前言
日常開(kāi)發(fā)部署后端服務(wù)時(shí),常會(huì)遇到一個(gè)高頻難題:前端多域名訪問(wèn)后端接口、Nginx 反向代理 + 后端自帶跨域配置,雙重沖突導(dǎo)致跨域報(bào)錯(cuò)、OPTIONS 預(yù)檢請(qǐng)求失敗、接口請(qǐng)求異常。
前段時(shí)間部署項(xiàng)目,后端部署在本地127.0.0.1:8270,前端對(duì)接多個(gè)業(yè)務(wù)域名,包含test1.com、test2.com、test3.com等。
初期出現(xiàn)嚴(yán)重跨域問(wèn)題:
- 后端自帶跨域響應(yīng)頭,+ Nginx 額外配置跨域,出現(xiàn)重復(fù)跨域頭;
- 多域名訪問(wèn),跨域白域無(wú)法統(tǒng)一管理;
- 前端 OPTIONS 預(yù)檢請(qǐng)求無(wú)響應(yīng),接口直接攔截;
- 跨域證書(shū)、請(qǐng)求頭權(quán)限受限,POST、PUT 等請(qǐng)求報(bào)錯(cuò)。
本文完整記錄,我如何通過(guò) Nginx 配置優(yōu)化,一站式徹底解決多域名跨域、重復(fù)請(qǐng)求頭、預(yù)檢失敗全流程問(wèn)題。
一、問(wèn)題根源分析
1. 核心矛盾
后端服務(wù)本身配置了跨域響應(yīng)頭,前端通過(guò) Nginx 反向代理訪問(wèn),若 Nginx 再疊加跨域配置,會(huì)造成:
Access-Control-Allow-Origin重復(fù)報(bào)錯(cuò);- 多域名白名單無(wú)法統(tǒng)一管控;
- 瀏覽器跨域校驗(yàn)規(guī)則沖突。
2. 特殊問(wèn)題
現(xiàn)代前端請(qǐng)求中,POST、PUT、DELETE、帶Content-Type、Authorization請(qǐng)求頭的接口,會(huì)觸發(fā) OPTIONS 預(yù)檢請(qǐng)求。
3. 業(yè)務(wù)需求
項(xiàng)目需要支持多個(gè)前端域名訪問(wèn):
- test1.com
- test2.com
- test3.com
- 同時(shí)兼容 www 子域名訪問(wèn)
二、解決方案整體思路
采用Nginx 全局接管跨域方案,核心思路四步走:
- 屏蔽后端跨域頭:禁止后端返回的跨域相關(guān)頭信息,避免重復(fù)沖突;
- 配置多域名白名單:正則匹配合法域名,動(dòng)態(tài)配置跨域來(lái)源;
- 攔截 OPTIONS 預(yù)檢請(qǐng)求:Nginx 直接返回 204 狀態(tài)碼 + 標(biāo)準(zhǔn)跨域頭,不轉(zhuǎn)發(fā)后端;
- 常規(guī)請(qǐng)求統(tǒng)一附加跨域頭:所有正常接口請(qǐng)求,統(tǒng)一添加合規(guī)跨域配置。
全程不修改后端代碼,純 Nginx 配置優(yōu)化,零業(yè)務(wù)改動(dòng)、低風(fēng)險(xiǎn)、一鍵生效。
三、分步落地配置優(yōu)化
第一步:屏蔽后端原生跨域響應(yīng)頭
問(wèn)題核心源頭就是「后端 + Nginx 雙重跨域」,優(yōu)先禁用后端所有跨域相關(guān)頭,杜絕沖突。
使用proxy_hide_header指令,屏蔽后端返回的跨域關(guān)鍵頭:
# 1. 先統(tǒng)一隱藏后端所有跨域頭(解決重復(fù)沖突問(wèn)題) proxy_hide_header Access-Control-Allow-Origin; proxy_hide_header Access-Control-Allow-Methods; proxy_hide_header Access-Control-Allow-Headers; proxy_hide_header Access-Control-Allow-Credentials;
配置作用:后端無(wú)論如何配置跨域,都不會(huì)傳遞到前端,所有跨域邏輯全權(quán)交給 Nginx 控制。
第二步:配置多域名跨域白名單
采用$http_origin獲取訪問(wèn)來(lái)源,通過(guò)正則匹配合法域名,動(dòng)態(tài)賦值跨域來(lái)源,支持主域名 + www 子域名。
覆蓋當(dāng)前所有業(yè)務(wù)域名:
- test1.com
- test2.com
- test3.com
# 2. 配置多域名白名單,動(dòng)態(tài)匹配合法來(lái)源
set $cors_origin "";
if ($http_origin ~* "^https://(www\.)?test1\.com$") {
set $cors_origin $http_origin;
}
if ($http_origin ~* "^https://(www\.)?test2\.com$") {
set $cors_origin $http_origin;
}
if ($http_origin ~* "^https://(www\.)?test3\.com$") {
set $cors_origin $http_origin;
}
- 正則
(www\.)?:兼容有無(wú) www 前綴; - 僅匹配合法域名,非法來(lái)源不賦值,杜絕跨域漏洞;
- 動(dòng)態(tài)賦值,符合瀏覽器跨域同源策略要求。
第三步:特殊處理 OPTIONS 預(yù)檢請(qǐng)求
前端復(fù)雜請(qǐng)求必先發(fā)送 OPTIONS 預(yù)檢,后端無(wú)對(duì)應(yīng)處理邏輯,極易報(bào)錯(cuò)。
解決方案:Nginx 直接攔截 OPTIONS 請(qǐng)求,返回 204 無(wú)內(nèi)容狀態(tài)碼,并附加完整跨域頭,無(wú)需轉(zhuǎn)發(fā)后端:
# 3. 攔截OPTIONS預(yù)檢請(qǐng)求,直接返回204狀態(tài)碼
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,PUT,DELETE" always;
add_header Access-Control-Allow-Headers "Content-Type,Authorization" always;
add_header Access-Control-Allow-Credentials "true" always;
return 204;
}
- 配置全量請(qǐng)求方式:GET/POST/PUT/DELETE/OPTIONS;
- 放行常用請(qǐng)求頭:格式頭、授權(quán)頭;
- 開(kāi)啟跨域憑證支持,適配登錄鑒權(quán)場(chǎng)景。
第四步:常規(guī)接口統(tǒng)一附加跨域頭
除預(yù)檢請(qǐng)求外,所有 GET、POST 等正常業(yè)務(wù)請(qǐng)求,統(tǒng)一添加跨域響應(yīng)頭,保證接口正常訪問(wèn):
# 4. 正常業(yè)務(wù)請(qǐng)求,統(tǒng)一添加跨域配置 add_header Access-Control-Allow-Origin $cors_origin always; add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,PUT,DELETE" always; add_header Access-Control-Allow-Headers "Content-Type,Authorization" always; add_header Access-Control-Allow-Credentials "true" always;
always關(guān)鍵字至關(guān)重要:無(wú)論響應(yīng)狀態(tài)碼 200/400/500,都強(qiáng)制攜帶跨域頭,避免異常接口跨域失效。
第五步:保留原有反向代理核心配置
跨域配置完全獨(dú)立隔離,原有反向代理、IP 轉(zhuǎn)發(fā)、超時(shí)、WebSocket 升級(jí)等配置完全保留,不影響原有業(yè)務(wù)運(yùn)行:
# 原有反向代理配置,完全保留無(wú)修改 proxy_pass http://127.0.0.1:8270; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; add_header X-Cache $upstream_cache_status; proxy_set_header X-Host $host:$server_port; proxy_set_header X-Scheme $scheme; proxy_connect_timeout 30s; proxy_read_timeout 86400s; proxy_send_timeout 30s; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
四、完整最終 Nginx 配置
location / {
# 1. 先統(tǒng)一隱藏后端所有跨域頭(解決重復(fù)沖突問(wèn)題)
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;
proxy_hide_header Access-Control-Allow-Credentials;
# 2. 配置多域名白名單,動(dòng)態(tài)匹配合法來(lái)源
set $cors_origin "";
if ($http_origin ~* "^https://(www\.)?test1\.com$") {
set $cors_origin $http_origin;
}
if ($http_origin ~* "^https://(www\.)?test2\.com$") {
set $cors_origin $http_origin;
}
if ($http_origin ~* "^https://(www\.)?test3\.com$") {
set $cors_origin $http_origin;
}
# 3. 攔截OPTIONS預(yù)檢請(qǐng)求,直接返回204狀態(tài)碼
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,PUT,DELETE" always;
add_header Access-Control-Allow-Headers "Content-Type,Authorization" always;
add_header Access-Control-Allow-Credentials "true" always;
return 204;
}
# 4. 正常業(yè)務(wù)請(qǐng)求,統(tǒng)一添加跨域配置
add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "GET,POST,OPTIONS,PUT,DELETE" always;
add_header Access-Control-Allow-Headers "Content-Type,Authorization" always;
add_header Access-Control-Allow-Credentials "true" always;
# 原有反向代理核心配置,無(wú)任何修改
proxy_pass http://127.0.0.1:8270;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
proxy_set_header X-Host $host:$server_port;
proxy_set_header X-Scheme $scheme;
proxy_connect_timeout 30s;
proxy_read_timeout 86400s;
proxy_send_timeout 30s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
五、配置校驗(yàn)與上線步驟
校驗(yàn) Nginx 語(yǔ)法
nginx -t
若無(wú)報(bào)錯(cuò),說(shuō)明配置語(yǔ)法無(wú)誤。
平滑重載生效
systemctl reload nginx
平滑重啟,不中斷線上業(yè)務(wù)。
以上就是Nginx反向代理后端接口解決跨域沖突、預(yù)檢報(bào)錯(cuò)問(wèn)題全流程的詳細(xì)內(nèi)容,更多關(guān)于Nginx反向代理后端接口的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Nginx的超時(shí)keeplive_timeout配置步驟
Nginx 處理的每個(gè)請(qǐng)求均有相應(yīng)的超時(shí)設(shè)置,本文主要介紹了Nginx的超時(shí)keeplive_timeout配置步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
nginx.conf配置文件結(jié)構(gòu)小結(jié)
本文主要介紹了nginx.conf配置文件結(jié)構(gòu)小結(jié),nginx.conf主要由events、http、server、location、upstream等塊配置項(xiàng)和一些行配置項(xiàng)組成,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
Logrotate如何實(shí)現(xiàn)每小時(shí)切割日志文件
這篇文章主要介紹了Logrotate如何實(shí)現(xiàn)每小時(shí)切割日志文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
Nginx 中 ssl_buffer_size 參數(shù)調(diào)優(yōu)的具體實(shí)現(xiàn)
ssl_buffer_size 不是越大越好,也不是越小越快,它本質(zhì)是在首包響應(yīng)速度和 TLS 協(xié)議開(kāi)銷(xiāo)之間做取舍,本文主要介紹了Nginx 中 ssl_buffer_size 參數(shù)調(diào)優(yōu)的具體實(shí)現(xiàn),感興趣的可以了解一下2026-04-04
Nginx配置動(dòng)態(tài)代理后通過(guò)curl訪問(wèn)報(bào)403問(wèn)題
本文主要介紹了Nginx配置動(dòng)態(tài)代理后通過(guò)curl訪問(wèn)報(bào)403問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
如何通過(guò)nginx負(fù)載均衡跳轉(zhuǎn)https
這篇文章主要介紹了如何通過(guò)nginx負(fù)載均衡跳轉(zhuǎn)https的相關(guān)資料,需要的朋友可以參考下2018-09-09
nginx將https協(xié)議反向代理到http協(xié)議請(qǐng)求上的實(shí)現(xiàn)
本文主要介紹了nginx將https協(xié)議反向代理到http協(xié)議請(qǐng)求上的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-10-10

