AspNetCore原始碼解析_1_CORS中介軟體
阿新 • • 發佈:2020-03-16
# 概述
## 什麼是跨域
在前後端分離開發方式中,跨域是我們經常會遇到的問題。所謂的跨域,就是處於安全考慮,A域名向B域名發出Ajax請求,瀏覽器會拒絕,丟擲類似下圖的錯誤。
![image](https://fs.31huiyi.com/2c239b54-ad37-4680-bd95-7f76b656be0d.png)
## JSONP
JSONP不是標準跨域協議,更像是聰明程式設計師投機取巧的辦法。這種方式的原理就是js是沒有跨域限制的,你想想你引用bootstrap.js是不是網路地址放進來就可以用了。
**實際上,所有src屬性都不限制跨域的,比如img標籤使用跨域圖片是不會有問題的。**
過程大體分下面四步。
- 首先約定資料格式和回撥函式名
- A網站引用B網站的js
- B網站用約定好的回撥函式將資料包裹起來,在A引用的js裡返回
- A網站在回撥函式中獲取資料
這個方案的優點是相容性比較好,很古老的ie都可以支援,畢竟只是基於js的一個技巧,並沒有新的技術或協議。
缺點比較明顯,只支援GET,理解起來比較彆扭,呼叫失敗不會返回http狀態碼,安全性存在一定問題。
## CORS
CORS的全稱是Cross Origin Resource Sharing,翻譯過來就是跨域資源共享。
跨域問題本質就是瀏覽器處於安全考慮,阻止了客戶端跨域請求。但說到底,客戶端請求安不安全還不是服務端說了算的,服務端都說我們家大米你們隨便吃,瀏覽器還阻止,這不是礙事嗎,你個物業還當自己業主啦?
但是瀏覽器也不能隨便放行,畢竟網上衝浪的不僅有正經客人,還有小偷,真出問題了還得吐槽物業稀爛。瀏覽器說,服務端,這個客戶端要去你家吃大米,你得告訴我你同不同意啊,服務端說我咋告訴你啊,我總不能來個人就衝著崗亭喊 I'M OK吧。瀏覽器說那我們搞個協議吧,整個網際網路小區都按這個規範來,你們就按這個格式回覆我。
這個協議就是CORS了。
graph LR;
A(客戶端)-->B(不帶Orgin跨域請求);
B-->C(瀏覽器拒絕);
A-->D(帶Origin跨域請求);
D-->E(服務端返回白名單);
E-->F(白名單內);
E-->G(白名單外);
F-->H(瀏覽器放行);
G-->C
CORS的缺點就是IE10以下不支援,如果你的專案需要相容這些瀏覽器的話需要注意。
關於CORS協議詳細的內容看這篇文章
> http://www.ruanyifeng.com/blog/2016/04/cors.html
## 怎麼實現CORS
CORS說白了其實就是在響應頭裡加東西,你可以在運維環節比如nginx加,可以在程式碼里加,常見的做法是中介軟體統一處理。AspNetCore為我們提供了CORS中介軟體。
## AspNetCore_CORS中介軟體的使用
使用CORS中介軟體兩句程式碼就夠了,在Startup檔案中
```csharp
//注入CORS相關的服務,配置跨域策略 [CorsPolicy]
public void ConfigureServices(IServiceCollection services)
{
//策略1,允許所有域名跨域訪問
config.AddPolicy("policy1", policy => {
policy.AllowAnyOrigin().
AllowAnyMethod().
AllowAnyOrigin().
AllowAnyMethod();
//注意:AllowAnyOrigin和AllowCredential不能同時出現,否則會報錯
//AllowCredential即是否允許客戶端傳送cookie,基於安全原因,CORS協議規定不允許AllowOrigin為萬用字元的情況下設定允許傳送cookie
//.AllowCredentials();
});
//策略2,僅允許特定域名、方法、請求頭訪問
config.AddPolicy("policy2",policy=> {
//只允許https://www.holdengong.com跨域訪問
policy.WithOrigins("https://www.holdengong.com")
//只允許get,post方法
.WithMethods("get", "post")
//請求頭中只允許有Authorization
.WithHeaders("Authorization")
//對於複雜請求,瀏覽器會首先發送預檢請求(OPTIONS),服務端返回204,並在響應頭中返回跨域設定
//此處可以設定預檢請求的有效時長,即30分鐘內不會再檢查是否允許跨域
.SetPreflightMaxAge(TimeSpan.FromMinutes(30));
});
}
//使用CORS中介軟體, 指定使用CorsPolicy
public void Configure(IApplicationBuilder app)
{
app.UseCors("CorsPolicy");
}
```
**注意:AllowAnyOrigin和AllowCredential不能同時配置,否則會報錯。如果要允許客戶端傳送cookie的話,只能使用WithOrgin來執行允許跨域白名單**
微軟使用的策略設計模式,方便我們靈活使用跨域策略。比如,開發環境允許localhost跨域訪問,方便開發除錯,正式環境只允許指定域名訪問。
## 原始碼解析
### 核心物件
```csharp
services.TryAdd(ServiceDescriptor.T