欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Nginx?代理解決跨域問題多種情況分析

 更新時(shí)間:2022年01月19日 10:48:26   作者:酒香逢  
這篇文章主要介紹了Nginx?代理解決跨域問題分析,通過用網(wǎng)站8080訪問Nginx代理后的接口地址,報(bào)錯(cuò)分為多種情況,每種情況給大家詳細(xì)分析,感興趣的朋友一起看看吧

何為跨域問題

跨域本人經(jīng)過兩天的磨練,大量地翻閱網(wǎng)上資料,通俗地講,就是,同一ip,同一域名,不同端口下,需要互相訪問,需要cookie的傳遞以及數(shù)據(jù)的獲取。

一般在項(xiàng)目中,前后端完全分離,因此訪問的端口號(hào)不同,比如:localhost:8090(前端)發(fā)送到localhost:8001(后端)請(qǐng)求數(shù)據(jù),此時(shí)前后端就出現(xiàn)了跨域問題。下面緊接著給大家介紹Nginx 代理解決跨域問題分析,內(nèi)容如下所示:

當(dāng)你遇到跨域問題,不要立刻就選擇復(fù)制去嘗試。請(qǐng)?jiān)敿?xì)看完這篇文章再處理 。我相信它能幫到你。

分析前準(zhǔn)備:

前端網(wǎng)站地址:http://localhost:8080

服務(wù)端網(wǎng)址:http://localhost:59200

首先保證服務(wù)端是沒有處理跨域的,其次,先用postman測(cè)試服務(wù)端接口是正常的

當(dāng)網(wǎng)站8080去訪問服務(wù)端接口時(shí),就產(chǎn)生了跨域問題,那么如何解決?接下來我把跨域遇到的各種情況都列舉出來并通過nginx代理的方式解決(后臺(tái)也是一樣的,只要你理解的原理)。

跨域主要涉及4個(gè)響應(yīng)頭:

Access-Control-Allow-Origin 用于設(shè)置允許跨域請(qǐng)求源地址 (預(yù)檢請(qǐng)求和正式請(qǐng)求在跨域時(shí)候都會(huì)驗(yàn)證)

Access-Control-Allow-Headers跨域允許攜帶的特殊頭信息字段(只在預(yù)檢請(qǐng)求驗(yàn)證)

Access-Control-Allow-Methods跨域允許的請(qǐng)求方法或者說HTTP動(dòng)詞(只在預(yù)檢請(qǐng)求驗(yàn)證)

Access-Control-Allow-Credentials 是否允許跨域使用cookies,如果要跨域使用cookies,可以添加上此請(qǐng)求響應(yīng)頭,值設(shè)為true(設(shè)置或者不設(shè)置,都不會(huì)影響請(qǐng)求發(fā)送,只會(huì)影響在跨域時(shí)候是否要攜帶cookies,但是如果設(shè)置,預(yù)檢請(qǐng)求和正式請(qǐng)求都需要設(shè)置)。不過不建議跨域使用(項(xiàng)目中用到過,不過不穩(wěn)定,有些瀏覽器帶不過去),除非必要,因?yàn)橛泻芏喾桨缚梢源妗?/p>

網(wǎng)上很多文章都是告訴你直接Nginx添加這幾個(gè)響應(yīng)頭信息就能解決跨域,當(dāng)然大部分情況是能解決,但是我相信還是有很多情況,明明配置上了,也同樣會(huì)報(bào)跨域問題。

什么是預(yù)檢請(qǐng)求?:當(dāng)發(fā)生跨域條件時(shí)候,覽器先詢問服務(wù)器,當(dāng)前網(wǎng)頁所在的域名是否在服務(wù)器的許可名單之中,以及可以使用哪些HTTP動(dòng)詞和頭信息字段。只有得到肯定答復(fù),瀏覽器才會(huì)發(fā)出正式的XMLHttpRequest請(qǐng)求,否則就報(bào)錯(cuò)。如下圖

開始動(dòng)手模擬:

Nginx代理端口:22222 ,配置如下

server {
        listen       22222;
        server_name  localhost;
        location  / {
            proxy_pass  http://localhost:59200;
        }
}

測(cè)試代理是否成功,通過Nginx代理端口2222再次訪問接口,可以看到如下圖通過代理后接口也是能正常訪問

接下來開始用網(wǎng)站8080訪問Nginx代理后的接口地址,報(bào)錯(cuò)情況如下↓↓↓

情況1:

Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

通過錯(cuò)誤信息可以很清晰的定位到錯(cuò)誤(注意看標(biāo)紅部分)priflight說明是個(gè)預(yù)請(qǐng)求,CORS 機(jī)制跨域會(huì)首先進(jìn)行 preflight(一個(gè) OPTIONS 請(qǐng)求), 該請(qǐng)求成功后才會(huì)發(fā)送真正的請(qǐng)求。 這一設(shè)計(jì)旨在確保服務(wù)器對(duì) CORS 標(biāo)準(zhǔn)知情,以保護(hù)不支持 CORS 的舊服務(wù)器

通過錯(cuò)誤信息,我們可以得到是預(yù)檢請(qǐng)求的請(qǐng)求響應(yīng)頭缺少了Access-Control-Allow-Origin,錯(cuò)哪里,我們改哪里就好了。修改Nginx配置信息如下(紅色部分為添加部分),缺什么就補(bǔ)什么,很簡(jiǎn)單明了

server {
        listen       22222;
        server_name  localhost;
        location  / {
           add_header Access-Control-Allow-Origin 'http://localhost:8080';
           proxy_pass  http://localhost:59200; 
        }
    }

哈哈,當(dāng)滿懷歡喜的以為能解決后,發(fā)現(xiàn)還是報(bào)了同樣的問題

不過我們的配置沒什么問題,問題在Nginx,下圖鏈接http://nginx.org/en/docs/http/ngx_http_headers_module.html

add_header 指令用于添加返回頭字段,當(dāng)且僅當(dāng)狀態(tài)碼為圖中列出的那些時(shí)有效。如果想要每次響應(yīng)信息都攜帶頭字段信息,需要在最后添加always(經(jīng)我測(cè)試,只有Access-Control-Allow-Origin這個(gè)頭信息需要加always,其他的不加always也會(huì)攜帶回來),那我們加上試試

server {
        listen       22222;
        server_name  localhost;
        location  / {
           add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
           proxy_pass  http://localhost:59200; 
        }
    }

修改了配置后,發(fā)現(xiàn)生效了,當(dāng)然不是跨域就解決了,是上面這個(gè)問題已經(jīng)解決了,因?yàn)閳?bào)錯(cuò)內(nèi)容已經(jīng)變了

情況2:

Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

通過報(bào)錯(cuò)信息提示可以得知,是跨域?yàn)g覽器默認(rèn)行為的預(yù)請(qǐng)求(option請(qǐng)求)沒有收到ok狀態(tài)碼,此時(shí)再修改配置文件,當(dāng)請(qǐng)求為option請(qǐng)求時(shí)候,給瀏覽器返回一個(gè)狀態(tài)碼(一般是204)

server {
        listen       22222;
        server_name  localhost;
        location  / {
           add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
           if ($request_method = 'OPTIONS') {
                return 204;
           }
           proxy_pass  http://localhost:59200; 
        }
    }

當(dāng)配置完后,發(fā)現(xiàn)報(bào)錯(cuò)信息變了

情況3:

Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

意思就是預(yù)請(qǐng)求響應(yīng)頭Access-Control-Allow-Headers中缺少頭信息authorization(各種情況會(huì)不一樣,在發(fā)生跨域后,在自定義添加的頭信息是不允許的,需要添加到請(qǐng)求響應(yīng)頭Access-Control-Allow-Headers中,以便瀏覽器知道此頭信息的攜帶是服務(wù)器承認(rèn)合法的,我這里攜帶的是authorization,其他的可能是token之類的,缺什么加什么),知道了問題所在,然后修改配置文件,添加對(duì)應(yīng)缺少的部分,再試試

server {
        listen       22222;
        server_name  localhost;
        location  / {
           add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
           if ($request_method = 'OPTIONS') {
               add_header Access-Control-Allow-Headers 'authorization'; #為什么寫在if里面而不是接著Access-Control-Allow-Origin往下寫?因?yàn)檫@里只有預(yù)檢請(qǐng)求才會(huì)檢查
               return 204; 
          } 
        proxy_pass http://localhost:59200; 
    }
}

此時(shí)發(fā)現(xiàn)報(bào)錯(cuò)問題又回到了情況1

經(jīng)測(cè)試驗(yàn)證,只要if ($request_method = 'OPTIONS') 里面寫了add_header ,當(dāng)為預(yù)檢請(qǐng)求時(shí)外部配置的都會(huì)失效,為什么? ↓↓。

官方文檔是這樣說的:

There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.

意思就是當(dāng)前層級(jí)無 add_header 指令時(shí),則繼承上一層級(jí)的add_header。相反的若當(dāng)前層級(jí)有了add_header,就應(yīng)該無法繼承上一層的add_header。

配置修改如下:

server {
        listen       22222;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080';
                add_header Access-Control-Allow-Headers 'authorization';
                return 204;
            }
            proxy_pass  http://localhost:59200; 
        }
    }

此時(shí)改完發(fā)現(xiàn)跨域問題已經(jīng)解決了,

不過以上雖然解決了跨域問題,但是考慮后期可能Nginx版本更新,不知道這個(gè)規(guī)則會(huì)不會(huì)被修改,考慮到這樣的寫法可能會(huì)攜帶上兩個(gè)Access-Control-Allow-Origin ,這種情況也是不允許的,下面會(huì)說到。所以配置適當(dāng)修改如下:

server {
        listen       22222;
        server_name  localhost;
        location  / {
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080';
                add_header Access-Control-Allow-Headers 'authorization';
                return 204;
            }
            if ($request_method != 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
            }
            proxy_pass  http://localhost:59200; 
        }
    }

還沒完,繼續(xù)聊 ↓↓

情況4:

比較早期的API可能只用到了POST和GET請(qǐng)求,而Access-Control-Allow-Methods這個(gè)請(qǐng)求響應(yīng)頭跨域默認(rèn)只支持POST和GET,當(dāng)出現(xiàn)其他請(qǐng)求類型時(shí)候,同樣會(huì)出現(xiàn)跨域異常。

比如,我這里將請(qǐng)求的API接口請(qǐng)求方式從原來的GET改成PUT,在發(fā)起一次試試。在控制臺(tái)上會(huì)拋出錯(cuò)誤:

Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.

報(bào)錯(cuò)內(nèi)容也講的很清楚,在這個(gè)預(yù)請(qǐng)求中,PUT方法是不允許在跨域中使用的,我們需要改下Access-Control-Allow-Methods的配置(缺什么加上么,這里我只加了PUT,可以自己加全一點(diǎn)),讓瀏覽器知道服務(wù)端是允許的

server {
    listen 22222;
    server_name localhost;
    location / {
        if ($request_method = 'OPTIONS') {
            add_header Access-Control-Allow-Origin 'http://localhost:8080';
            add_header Access-Control-Allow-Headers 'content-type,authorization';
            add_header Access-Control-Allow-Methods 'PUT';#為這么只加在這個(gè)if中,不再下面的if也加上?因?yàn)檫@里只有預(yù)檢請(qǐng)求會(huì)校驗(yàn),當(dāng)然你加上也沒事。
            return 204;
        }
        if ($request_method != 'OPTIONS') {
            add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
        }
        proxy_pass http://localhost:59200;
    }
}

這里注意一下,改成PUT類型后,Access-Control-Allow-Headers請(qǐng)求響應(yīng)頭又會(huì)自動(dòng)校驗(yàn)content-type這個(gè)請(qǐng)求頭,和情況3是一樣的,缺啥補(bǔ)啥就行了。如果不加上content-type,則會(huì)報(bào)如下錯(cuò)誤。(想簡(jiǎn)單的話,Access-Control-Allow-Headers和Access-Control-Allow-Methods可以設(shè)置為* ,表示全都匹配。但是Access-Control-Allow-Origin就不建議設(shè)置成 * 了,為了安全考慮,限制域名是很有必要的。)

都加上后,問題就解決了,這里報(bào)405是我服務(wù)端這個(gè)接口只開放了GET,沒有開放PUT,而此刻我將此接口用PUT方法去請(qǐng)求,所以接口會(huì)返回這個(gè)狀態(tài)碼。

情況5:

最后再說一種情況,就是后端處理了跨域,就不需要自己在處理了(這里吐槽下,某些后端工程師自己改服務(wù)端代碼解決跨域,但是又不理解其中原理,網(wǎng)上隨便找段代碼黏貼,導(dǎo)致響應(yīng)信息可能處理不完全,如method沒添加全,headers沒加到點(diǎn)上,自己用的那個(gè)可能復(fù)制過來的并不包含實(shí)際項(xiàng)目所用到的,沒有添加options請(qǐng)求返回狀態(tài)碼等,導(dǎo)致Nginx再用通用的配置就會(huì)可能報(bào)以下異常)

Access to XMLHttpRequest at 'http://localhost:22222/api/Login/TestGet' from origin 'http://localhost:8080' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, http://localhost:8080', but only one is allowed.

意思就是此刻Access-Control-Allow-Origin請(qǐng)求響應(yīng)頭返回了多個(gè),而只允許有一個(gè),這種情況當(dāng)然修改配置去掉Access-Control-Allow-Origin這個(gè)配置就可以了,不過遇到這種情況,建議Nginx配置和服務(wù)端自己解決跨域只選其一。(這里注意如果按我上面的寫法,if $request_method = 'OPTIONS' 這個(gè)里面的Access-Control-Allow-Origin可不能刪除,刪除!='OPTIONS'里面的就好了,因?yàn)檫@里如果是預(yù)檢請(qǐng)求直接就ruturn了,請(qǐng)求不會(huì)再轉(zhuǎn)發(fā)到59200服務(wù),如果也刪除了,就會(huì)報(bào)和情況1一樣的錯(cuò)誤。所以為什么說要不服務(wù)端代碼層面解決跨域,要不就Nginx代理解決,不要混著搞,不然不明白原理的人,網(wǎng)上找一段代碼貼就很可能解決不了問題)

↓↓↓↓↓

再貼一份完整配置(*號(hào)根據(jù)自己‘喜好’填寫):

server {
        listen       22222;
        server_name  localhost;
        location  / {
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080';
                add_header Access-Control-Allow-Headers '*';
                add_header Access-Control-Allow-Methods '*';
                add_header Access-Control-Allow-Credentials 'true';
                return 204;
            }
            if ($request_method != 'OPTIONS') {
                add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
                add_header Access-Control-Allow-Credentials 'true';
            }
            proxy_pass  http://localhost:59200; 
        }
    }

或者:

server {
        listen       22222;
        server_name  localhost;
        location  / {
            add_header Access-Control-Allow-Origin 'http://localhost:8080' always;
            add_header Access-Control-Allow-Headers '*';
            add_header Access-Control-Allow-Methods '*';
            add_header Access-Control-Allow-Credentials 'true';
            if ($request_method = 'OPTIONS') {
                return 204;
            }
            proxy_pass  http://localhost:59200; 
        }
    }

最后,這是一篇解決跨域遇到問題解決問題的過程,如果認(rèn)真看完了,我相信應(yīng)該都能很容易的理解,并且在實(shí)際使用中自己解決該問題,希望能幫助到大家,以上內(nèi)容都是自己理解自己測(cè)試碼出來的,如有理解不對(duì)的地方,望大家指正。

到此這篇關(guān)于Nginx 代理解決跨域問題分析的文章就介紹到這了,更多相關(guān)nginx 代理解決跨域內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • nginx url自動(dòng)加斜杠及301重定向的問題

    nginx url自動(dòng)加斜杠及301重定向的問題

    這篇文章主要介紹了nginx url自動(dòng)加斜杠及301重定向的問題的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • nginx如何設(shè)置禁止訪問PHP腳本

    nginx如何設(shè)置禁止訪問PHP腳本

    禁止訪問?PHP?腳本可以通過?Nginx?服務(wù)器配置中的多種方式來實(shí)現(xiàn),這篇文章主要為大家整理了一些常見的方法,感興趣的小伙伴可以參考下
    2023-09-09
  • nginx訪問控制的兩種方法

    nginx訪問控制的兩種方法

    這篇文章主要介紹了關(guān)于nginx訪問控制的兩種方法,一種是基于Basic Auth認(rèn)證,另一種是基于IP的訪問控制,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-03-03
  • Nginx防盜鏈與服務(wù)優(yōu)化配置的全過程

    Nginx防盜鏈與服務(wù)優(yōu)化配置的全過程

    由于Nginx本身的一些優(yōu)點(diǎn),輕量,開源,易用,越來越多的公司使用nginx作為自己公司的web應(yīng)用服務(wù)器,下面這篇文章主要給大家介紹了關(guān)于Nginx防盜鏈與服務(wù)優(yōu)化配置的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • Nginx配置詳解(推薦)

    Nginx配置詳解(推薦)

    Nginx功能豐富,可作為HTTP服務(wù)器,也可作為反向代理服務(wù)器,郵件服務(wù)器。支持FastCGI、SSL、Virtual Host、URL Rewrite、Gzip等功能
    2017-05-05
  • Nginx可視化管理軟件(Nginx Proxy Manager)的使用

    Nginx可視化管理軟件(Nginx Proxy Manager)的使用

    Nginx Proxy Manager是一款開源的Nginx可視化管理界面,本文就來介紹一下Nginx Proxy Manager的使用,感興趣的可以了解一下
    2024-03-03
  • 詳解Nginx的配置函數(shù)對(duì)于請(qǐng)求體的讀取

    詳解Nginx的配置函數(shù)對(duì)于請(qǐng)求體的讀取

    這篇文章主要介紹了Nginx的配置函數(shù)對(duì)于請(qǐng)求體的讀取,深入Nginx的內(nèi)核配置中進(jìn)行講解,需要的朋友可以參考下
    2015-12-12
  • CentOS6.6 安裝 Tengine 筆記

    CentOS6.6 安裝 Tengine 筆記

    這篇文章主要介紹了CentOS6.6 安裝 Tengine 筆記,本文講解了安裝必要的編譯環(huán)境好、安裝需要的組件、安裝Tengine等步驟,需要的朋友可以參考下
    2015-03-03
  • Nginx反斜杠自動(dòng)解碼問題解決方法

    Nginx反斜杠自動(dòng)解碼問題解決方法

    這篇文章主要介紹了Nginx反斜杠自動(dòng)解碼問題解決方法,有些時(shí)候是不需要解碼的,可nginx缺會(huì)自動(dòng)解碼,本文講解的就是如何解決這個(gè)問題,需要的朋友可以參考下
    2015-02-02
  • nginx請(qǐng)求時(shí)找路徑問題解決

    nginx請(qǐng)求時(shí)找路徑問題解決

    當(dāng)你安裝了nginx的時(shí)候,為nginx配置了如下的location,想要去訪問路徑下面的內(nèi)容,可是總是出現(xiàn)404,找不到文件,這是什么原因呢,今天我們就來解決這個(gè)問題,感興趣的朋友一起看看吧
    2023-10-10

最新評(píng)論