[CORS:跨域資源共享] ASP.NET Web API自身對CORS的支持: CORS授權檢驗的實施

通過《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分別表示報頭名稱和值。


using System;
using System.Collections.Generic;

namespace System.Web.Cors
{
    public class CorsResult
    {
        public CorsResult();

        public IList<string> AllowedExposedHeaders { get; }
        public IList<string> AllowedHeaders { get; }
        public IList<string> AllowedMethods { get; }
        public string AllowedOrigin { get; set; }
        public IList<string> ErrorMessages { get; }
        public bool IsValid { get; }
        public long? PreflightMaxAge { get; set; }
        public bool SupportsCredentials { get; set; }

        public virtual IDictionary<string, string> ToResponseHeaders();
        public override string ToString();
    }
}

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)。


public class CorsRequestContext
{
     public Uri         RequestUri { get; set; }
     public string      Host { get; set; }
     public string      HttpMethod { get; set; }    

     public string          Origin { get; set; }
     public bool            IsPreflight { get; }
     public string          AccessControlRequestMethod { get; set; }
     public ISet<string>    AccessControlRequestHeaders { get; }

     public IDictionary<string, object> Properties { get; }
 }

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方法中。


 public interface ICorsEngine
  {
      //評估策略
     CorsResult EvaluatePolicy(CorsRequestContext requestContext, CorsPolicy policy);
  }

在程序集System.Web.Cors.dll中定義了唯一的實現了ICorsEngine接口,即具有如下定義的類型System.Web.Cors.CorsEngine。如下面的代碼片斷所示,CorsEngine類型定義了3個輔助的虛方法(TryValidateOrigin、TryValidateMethod 和TryValidateHeaders)分別針對請求的源站點以及請求採用的HTTP方法和自定義報頭實施授權檢驗,其中後面兩個方法是專門爲預檢請求設計的。


 public class CorsEngine : ICorsEngine
   {
         public virtual CorsResult EvaluatePolicy(CorsRequestContext requestContext, CorsPolicy policy);

        public virtual bool TryValidateOrigin(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result);
        public virtual bool TryValidateMethod(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result);
        public virtual bool TryValidateHeaders(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result); 
     }

CorsPolicyProviderFactory一樣,ASP.NET Web API使用的CorsEngine需要註冊到當前HttpConfiguration,註冊的CorsEngine同樣是被添加到HttpConfiguration的屬性字典之中。CorsEngine的註冊可以通過調用HttpConfiguration如下所示的擴展方法SetCorsEngine來完成。另一個擴展方法GetCorsEngine用於獲取註冊的CorsEngine,如果在調用此方法時CorsEngine尚未被註冊,一個CorsEngine對象會被創建出來並自動註冊到HttpConfiguration上。


 public static class CorsHttpConfigurationExtensions
    {
        //其他成員
         public static void SetCorsEngine(this HttpConfiguration httpConfiguration, ICorsEngine corsEngine);
        public static ICorsEngine GetCorsEngine(this HttpConfiguration httpConfiguration);
   }

本文轉載:http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-07.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章