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

Nginx輕松搞定跨域問題完整過程

 更新時間:2023年08月28日 11:34:33   作者:遠方并不遠。  
這篇文章主要給大家介紹了關于Nginx輕松搞定跨域問題的相關資料,大家在使用nginx進行服務器管理,經(jīng)常會遇到跨域問題,文中將解決方法介紹的非常詳細,需要的朋友可以參考下

當你遇到跨域問題,不要立刻就選擇復制去嘗試。請詳細看完這篇文章再處理 。我相信它能幫到你。

分析前準備:

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

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

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

跨域主要涉及4個響應頭:

  • Access-Control-Allow-Origin  用于設置允許跨域請求源地址 (預檢請求和正式請求在跨域時候都會驗證)
  • Access-Control-Allow-Headers  跨域允許攜帶的特殊頭信息字段 (只在預檢請求驗證)
  • Access-Control-Allow-Methods  跨域允許的請求方法或者說HTTP動詞 (只在預檢請求驗證)
  • Access-Control-Allow-Credentials  是否允許跨域使用cookies,如果要跨域使用cookies,可以添加上此請求響應頭,值設為true(設置或者不設置,都不會影響請求發(fā)送,只會影響在跨域時候是否要攜帶cookies,但是如果設置,預檢請求和正式請求都需要設置)。不過不建議跨域使用(項目中用到過,不過不穩(wěn)定,有些瀏覽器帶不過去),除非必要,因為有很多方案可以代替。

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

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

開始動手模擬:

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

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

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

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

情況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.

通過錯誤信息可以很清晰的定位到錯誤(注意看標紅部分)priflight說明是個預請求,CORS 機制跨域會首先進行 preflight(一個 OPTIONS 請求), 該請求成功后才會發(fā)送真正的請求。這一設計旨在確保服務器對 CORS 標準知情,以保護不支持 CORS 的舊服務器

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

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

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

不過我們的配置沒什么問題,問題在Nginx

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

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)生效了,當然不是跨域就解決了,是上面這個問題已經(jīng)解決了,因為報錯內(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.

通過報錯信息提示可以得知,是跨域瀏覽器默認行為的預請求(option請求)沒有收到ok狀態(tài)碼,此時再修改配置文件,當請求為option請求時候,給瀏覽器返回一個狀態(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; 
        }
    }

當配置完后,發(fā)現(xiàn)報錯信息變了

情況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.

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

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往下寫?因為這里只有預檢請求才會檢查               return 204;           }         proxy_pass http://localhost:59200;     }
}

此時發(fā)現(xiàn)報錯問題又回到了情況1

經(jīng)測試驗證,只要 if ($request_method = 'OPTIONS')  里面寫了  add_header  ,當為預檢請求時外部配置的都會失效,為什么?↓↓。

官方文檔是這樣說的:

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.

意思就是當前層級無  add_header  指令時,則繼承上一層級的 add_header 。相反的若當前層級有了 add_header ,就應該無法繼承上一層的 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; 
        }
    }

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

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

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請求,而 Access-Control-Allow-Methods 這個請求響應頭跨域默認只支持POST和GET,當出現(xiàn)其他請求類型時候,同樣會出現(xiàn)跨域異常。

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

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.

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

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';#為這么只加在這個if中,不再下面的if也加上?因為這里只有預檢請求會校驗,當然你加上也沒事。
            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 請求響應頭又會自動校驗 content-type 這個請求頭,和情況3是一樣的,缺啥補啥就行了。如果不加上 content-type ,則會報如下錯誤。

想簡單的話, Access-Control-Allow-Headers Access-Control-Allow-Methods 可以設置為  *  ,表示全都匹配。但是 Access-Control-Allow-Origin 就不建議設置成  *  了,為了安全考慮,限制域名是很有必要的。

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

情況5:

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

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 請求響應頭返回了多個,而只允許有一個,這種情況當然修改配置去掉 Access-Control-Allow-Origin 這個配置就可以了,不過遇到這種情況,建議Nginx配置和服務端自己解決跨域只選其一。

這里注意如果按我上面的寫法, if $request_method = 'OPTIONS'  這個里面的 Access-Control-Allow-Origin 可不能刪除,刪除 !='OPTIONS' 里面的就好了,因為這里如果是預檢請求直接就ruturn了,請求不會再轉發(fā)到59200服務,如果也刪除了,就會報和情況1一樣的錯誤。所以為什么說要不服務端代碼層面解決跨域,要不就Nginx代理解決,不要混著搞,不然不明白原理的人,網(wǎng)上找一段代碼貼就很可能解決不了問題

再貼一份完整配置( * 號根據(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; 
        }
    }

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

總結

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

相關文章

  • 利用Nginx實現(xiàn)URL重定向的簡單方法

    利用Nginx實現(xiàn)URL重定向的簡單方法

    使用Nginx的重定向功能時,除了可以重定向到新域名,還可以將請求重定向到特定的協(xié)議上,下面這篇文章主要給大家介紹了關于如何利用Nginx實現(xiàn)URL重定向的簡單方法,需要的朋友可以參考下
    2022-04-04
  • 詳解Nginx服務器中配置Sysguard模塊預防高負載的方案

    詳解Nginx服務器中配置Sysguard模塊預防高負載的方案

    這篇文章主要介紹了詳解Nginx服務器中配置Sysguard模塊預防高負載的方案,該模塊由阿里巴巴的團隊開發(fā),能夠設置負載閥值,比較強大,需要的朋友可以參考下
    2016-01-01
  • tomcat在nginx中的配置方式

    tomcat在nginx中的配置方式

    文章介紹了如何在Linux系統(tǒng)上安裝和配置Tomcat,并通過Nginx進行代理,首先,下載并解壓Tomcat壓縮包,然后啟動Tomcat并查看日志,接著,配置Nginx以代理Tomcat的8080端口,并確保80端口已開放,最后,重新加載Nginx配置并測試代理是否成功
    2024-12-12
  • nginx.pid打開失敗以及失效的解決方案

    nginx.pid打開失敗以及失效的解決方案

    在我們平常使用nginx的時候,經(jīng)常有可能會發(fā)現(xiàn)我們的pid找不到了,本文就介紹了nginx.pid打開失敗以及失效的解決方案,具有一定的參考價值,感興趣的可以了解一下
    2021-12-12
  • CentOS 4.0安裝配置Nginx的方法

    CentOS 4.0安裝配置Nginx的方法

    這篇文章主要介紹了CentOS 4.0安裝配置Nginx的方法,需要的朋友可以參考下
    2014-11-11
  • 本地通過nginx配置反向代理的全過程記錄

    本地通過nginx配置反向代理的全過程記錄

    這篇文章主要給大家介紹了關于本地通過nginx配置反向代理的全過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • nginx如何設置禁止訪問PHP腳本

    nginx如何設置禁止訪問PHP腳本

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

    nginx限流方案的實現(xiàn)(三種方式)

    一般對外暴露的系統(tǒng),在促銷或者黑客攻擊時會涌來大量的請求,為了保護系統(tǒng)不被瞬間到來的高并發(fā)流量給打垮, 就需要限流,這篇文章主要介紹了nginx限流方案的實現(xiàn),非常具有實用價值,需要的朋友可以參考下
    2018-05-05
  • 解析nginx server_name的具體使用

    解析nginx server_name的具體使用

    nginx server_name對于正確配置虛擬主機非常重要,本文主要介紹了解析nginx server_name的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-08-08
  • 詳解nginx中的日志配置

    詳解nginx中的日志配置

    日志對于統(tǒng)計排錯來說非常有利的,本文為大家總結了nginx日志相關的配置如access_log、log_format、open_log_file_cache等內(nèi)容,感興趣的小伙伴可以了解下
    2023-08-08

最新評論