通過《EnableCorsAttribute特性背后的故事》我們知道:由CorsPolicyProvider提供的CorsPolicy表示目標Action采用的資源授權策略,ASP.NET Web API最終需要利用它對具體的跨域資源請求實施授權檢驗并生成相應的CORS響應報頭。在ASP.NET Web API的應用編程接口中,資源授權檢驗的結果通過類型CorsResult來表示。
一、CorsResult
CorsResult定義在命名空間“System.Web.Cors”下,表示資源提供者針對具體跨域資源請求進行授權檢驗得到的結果,最終寫入響應的CORS報頭均通過此對象來生成。如下面的代碼片斷所示,CorsResult依然具有與6個CORS響應報頭對應的屬性,通過其方法ToResponseHeaders方法的字典表示由此6個屬性生成的CORS相應報頭,字典對象的Key和Value分別表示報頭名稱和值。
1: public class CorsResult
2: {
3: public string AllowedOrigin { get; set; }
4: public IList<string> AllowedExposedHeaders { get; }
5: public IList<string> AllowedHeaders { get; }
6: public IList<string> AllowedMethods { get; }
7: public long? PreflightMaxAge { get; set; }
8: public bool SupportsCredentials { get; set; }
9:
10: public IList<string> ErrorMessages { get; }
11: public bool IsValid { get; }
12:
13: public virtual IDictionary<string, string> ToResponseHeaders();
14: }
CorsResult具有一個布爾類型的屬性IsValid表示請求是否通過資源授權檢驗。如果該屬性返回False(沒有通過資源授權檢驗),另一個相關的屬性ErrorMessages會提供導致檢驗失敗的原因。IsValid是一個只讀屬性,它的值取決于通過ErrorMessages屬性表示的字符串列表是否為空。
二、CorsRequestContext
針對CORS的支持其實并不限于僅被使用在ASP.NET Web API上,用于根據提供的資源授權策略對跨域資源請求進行授權檢驗得引擎定義在程序集System.Web.Cors.dll中,定義在另一個程序集對于這些類型來說,除了CorsPolicy定義在程序集System.Web.Cors.dll,其余的類型均定義在程序集System.Web.Http.Cors.dll中的相關類型可以視為對這個核心CORS引擎的擴展。對于本節引入的類型來說,它具有的命名空間其實也體現了它所在的程序集。
對于ASP.NET Web API來說,CORS資源授權檢驗實施的目標是表示當請求的HttpRequestMessage對象,這個對象自然不可能使用在ASP.NET的核心CORS引擎中。對于后者,授權檢驗是針對一個System.Web.Cors.CorsRequestContext對象,它代表針對當前請求的上下文。如下面的代碼片斷所示,我們可以通過CorsRequestContext對象得到對應HTTP請求的地址(RequestUri)、主機名稱(Host)和采用的HTTP方法(HttpMethod)。
1: public class CorsRequestContext
2: {
3: public Uri RequestUri { get; set; }
4: public string Host { get; set; }
5: public string HttpMethod { get; set; }
6:
7: public string Origin { get; set; }
8: public bool IsPreflight { get; }
9: public string AccessControlRequestMethod { get; set; }
10: public ISet<string> AccessControlRequestHeaders { get; }
11:
12: public IDictionary<string, object> Properties { get; }
13: }
CorsRequestContext的Origin屬性返回通過請求的“Origin”報頭表示的源站點。我們可以利用其IsPreflight屬性判斷HTTP請求是否為一個預檢請求,這里對預檢請求的判斷標準與我們前面演示實例采用的完全一致:采用HTTP-OPTIONS方法摒棄同時具有“Origin”和“Access-Control-Request-Method”報頭。
對于針對預檢請求的CorsRequestContext,我們可以通過其屬性AccessControlRequestMethod和AccessControlRequestHeaders得到請求報頭“Access-Control-Request-Method”和“Access-Control-Request-Headers”的值。通過另一個字典類型的只讀屬性Properties,我們可以將任意對象作為屬性附加到該CorsRequestContext對象上。
三、CorsEngine
我們說ASP.NET 的核心CORS引擎定義在程序集System.Web.Cors.dll中,它主要體驗為這個名為CorsEngine的對象,其主要的使命在于:根據提供的資源授權策略(通過CorsPolicy類型表示)針對具體的跨域資源請求(通過CorsRequestContext類型表示)實施授權檢驗并得到相應的授權結果(通過CorsResult表示)。所有的CorsEngine類型均實現System.Web.Cors.ICorsEngine接口,如下面的代碼片斷所示,跨域資源請求的授權檢查就實現在其唯一的EvaluatePolicy方法中。
1: public interface ICorsEngine
2: {
3: CorsResult EvaluatePolicy(CorsRequestContext requestContext, CorsPolicy policy);
4: }
在程序集System.Web.Cors.dll中定義了唯一的實現了ICorsEngine接口,即具有如下定義的類型System.Web.Cors.CorsEngine。如下面的代碼片斷所示,CorsEngine類型定義了3個輔助的虛方法(TryValidateOrigin、TryValidateMethod 和TryValidateHeaders)分別針對請求的源站點以及請求采用的HTTP方法和自定義報頭實施授權檢驗,其中后面兩個方法是專門為預檢請求設計的。
1: public class CorsEngine : ICorsEngine
2: {
3: public virtual CorsResult EvaluatePolicy(CorsRequestContext requestContext, CorsPolicy policy);
4:
5: public virtual bool TryValidateOrigin(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result);
6: public virtual bool TryValidateMethod(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result);
7: public virtual bool TryValidateHeaders(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result);
8: }
CorsPolicyProviderFactory一樣,ASP.NET Web API使用的CorsEngine需要注冊到當前HttpConfiguration,注冊的CorsEngine同樣是被添加到HttpConfiguration的屬性字典之中。CorsEngine的注冊可以通過調用HttpConfiguration如下所示的擴展方法SetCorsEngine來完成。另一個擴展方法GetCorsEngine用于獲取注冊的CorsEngine,如果在調用此方法時CorsEngine尚未被注冊,一個CorsEngine對象會被創建出來并自動注冊到HttpConfiguration上。
1: public static class CorsHttpConfigurationExtensions
2: {
3: //其他成員
4: public static void SetCorsEngine(this HttpConfiguration httpConfiguration, ICorsEngine corsEngine);
5: public static ICorsEngine GetCorsEngine(this HttpConfiguration httpConfiguration);
6: }
CORS系列文章
[1] 同源策略與JSONP
[2] 利用擴展讓ASP.NET Web API支持JSONP
[3] W3C的CORS規范
[4] 利用擴展讓ASP.NET Web API支持CORS
[5] ASP.NET Web API自身對CORS的支持: 從實例開始
[6] ASP.NET Web API自身對CORS的支持: CORS授權策略的定義和提供
[7] ASP.NET Web API自身對CORS的支持: CORS授權檢驗的實施
[8] ASP.NET Web API自身對CORS的支持: CorsMessageHandler
文章列表