.Net Core 后台 + Apisix 網關 解決跨域訪問Cors問題


1, 什么是跨域

瀏覽器從一個域名的網頁去請求另一個域名的資源時,域名、端口、協議任一不同,都是跨域
域名:
 主域名不同 http://www.baidu.com/index.html -->http://www.sina.com/test.js
 子域名不同 http://www.666.baidu.com/index.html -->http://www.555.baidu.com/test.js
 域名和域名ip http://www.baidu.com/index.html -->http://180.149.132.47/test.js
端口:
 http://www.baidu.com:8080/index.html–> http://www.baidu.com:8081/test.js
協議:
 http://www.baidu.com:8080/index.html–> https://www.baidu.com:8080/test.js
備注:
 1、端口和協議的不同,只能通過后台來解決
 2、localhost和127.0.0.1雖然都指向本機,但也屬於跨域

當發生跨域訪問(cross-domain access),瀏覽器就無法正常從后台服務中獲取信息。所以必須要解決跨域問題。

 

2,跨域的種類

瀏覽器將CORS請求分成兩類:簡單請求(simple request)非簡單請求(not-so-simple request)。

只要同時滿足以下兩大條件,就屬於簡單請求。

1) 請求方法是以下三種方法之一:

HEAD
GET
POST

(2)HTTP的頭信息不超出以下幾種字段:

Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限於三個值 
    application/x-www-form-urlencoded(對發送內容進行編碼)
    multipart/form-data(上傳的表單內包含文件)
    text/plain(發送內容為純文本格式)

凡是不同時滿足上面兩個條件,就屬於非簡單請求。

 

對於簡單請求,瀏覽器直接發出CORS請求。具體來說,就是在頭信息之中,增加一個Origin字段。

Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0

上面的頭信息中,Origin字段用來說明,本次請求來自哪個源(協議 + 域名 + 端口)。服務器根據這個值,再根據自身的跨域設置,決定是否同意這次請求。

如果Origin指定的源,不在許可范圍內,服務器會返回一個正常的HTTP回應。瀏覽器發現,這個回應的頭信息沒有包含Access-Control-Allow-Origin字段(詳見下文),就知道出錯了,從而拋出一個錯誤,被XMLHttpRequestonerror回調函數捕獲。注意,這種錯誤無法通過狀態碼識別,因為HTTP回應的狀態碼有可能是200。

 

對於非簡單請求的CORS請求,會在正式通信之前,不需要用戶操作,瀏覽器自動發送一個OPTION請求(也叫做預檢操作)。

服務器收到預檢請求后,檢查這些特殊的請求方法和頭自己能否接受。如果服務器支持預檢中的Header和Methods,那么接下來就可以正常發送信息。

 

3,跨域的解決方案

跨域問題可以從三個方面着手解決:前端/后端/網關

前端很多的解決方案,例如Vue的話可以試試:axios解決跨域問題(vue-cli3.0)

.Net Core 3.1 的后端的解決方法也比較簡單,最懶的方法是在Startup.cs的Configure方法增加以下代碼:

   app.UseCors(builder =>
            {
                builder.AllowAnyMethod()
                    .AllowAnyHeader()
                    .SetIsOriginAllowed(_ => true) // =AllowAnyOrigin()
                    .AllowCredentials();
            });

將上述代碼插入到 app.UseRouting() 與 app.UseCors之間,則在全局范圍內取消了一切跨域訪問的限制。

或者,在ConfigureServices方法添加跨域設置,然后在Configure方法使用這個跨域設置也可以:

//ConfigureServices 設置允許所有來源跨域
            services.AddCors(options => options.AddPolicy("CorsPolicy",
            builder =>
            {
                builder.AllowAnyMethod()
                    .AllowAnyHeader()
                    .SetIsOriginAllowed(_ => true) // =AllowAnyOrigin()
                    .AllowCredentials();
            }));



//Configure 使用跨域配置
            app.UseCors("CorsPolicy");

 

如果不想全局都一個跨域的設置,而是每一個Controller設置每一個方法都有特定的跨域設置,則可以在Startup.cs文件的方法用AddCors方法添加若干個跨域設置,然后在對應的Controller或者方法上使用 [EnableCors] 屬性啟用 CORS。

詳情可以參考微軟官方文檔:在 ASP.NET Core 中啟用跨源請求 (CORS)

 

對於后台服務來說,一般都要配備網關。我這個項目選用了國人開源的Apisix網關。Apisix的使用就不啰嗦了,反正友好的文檔以及方便的Dashboard,相當的不錯。

前面說過,跨域請求的“非簡單請求”會首先發送一次OPTION請求(預檢操作)到服務器,等待服務器告知正常才正式執行請求。所以,務必務必,在網關設置允許的HTTP方法里,添加選擇OPTION

 

 如果后端已經開啟了CORS,則網關除了HTTP方法外無需留意其他的設置。但如果后端不設置的話,網關也一樣能解決跨域訪問

我們在Apisix網關的路由配置頁面的第三步“插件配置”里可以發現一個Cors,只需要將其啟用即可:

 

 相關的配置,Apisix也有詳細的文檔說明:cors

 

 

 

4,參考鏈接:

什么是跨域?如何解決跨域問題?

CORS簡單請求和非簡單請求

CORS請求的簡單請求和非簡單請求

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM