本文章是由機器翻譯。

ASP.NET Web API

ASP.NET Web API 2 中的 CORS 支援

Brock Allen

跨起源資源分享 (CORS) 是用於克服強加的瀏覽器的同源策略安全限制的 JavaScript 的全球資訊網協會 (W3C) 規範 (通常被認為一部分的 HTML5)。 同一起源政策意味著您 JavaScript 可以只進行 AJAX 調用回到同一起源的包含 Web 頁 ("原產地"指作為主機名稱、 協定和埠號的組合)。 例如,JavaScript 從 HTTP://foo.com 到 Web 頁上的不能進行 AJAX 調用到 HTTP://bar.com (或 HTTP://www.foo.com、 HTTPs://foo.com 或 HTTP://foo.com:999,為那件事)。

CORS 放寬這一限制,讓伺服器指示哪些起源允許調用它們。 CORS 通過瀏覽器執行的但必須在伺服器上,執行和ASP.NETWeb API 2 的最新的版本已充分 CORS 支援。 與 Web API 2,您可以配置策略以允許 JavaScript 用戶端從一個不同的起源訪問您的 Api。

CORS 基礎知識

要在 Web API 中使用新的 CORS 功能,就有助於理解 CORS 本身的細節,因為是對規範的 Web API 執行。 這些細節可能看起來賣弄學問的現在,但他們會有用以後理解 Web API 中可用的設置 — — 當你在調試 CORS 他們會幫你解決問題速度更快。

CORS 一般力學是 JavaScript 試圖使瀏覽器將"詢問"伺服器是否這允許通過發送標頭中的 HTTP 要求 (例如,起源) 的跨起源 AJAX 調用時。 伺服器指示所允許的 (例如,訪問-控制-允許-起源) 回應中返回的 HTTP 標頭。 對於每個不同的 URL,用戶端調用,這意味著不同的 Url 可以有不同的許可權進行此許可權檢查。

出身的除了 CORS 允許指示伺服器允許的 HTTP 方法,其中 HTTP 要求標頭的用戶端可以發送,用戶端可以讀取,和如果瀏覽器允許對自動發送或接收憑據 (cookie 或授權標頭) 的 HTTP 回應標頭。 請求和回應的其他標頭檔表明,這些功能允許使用。 在總結這些標頭圖 1 (注意的一些功能有沒有發送請求中的標頭 — — 僅回應)。

圖 1 CORS HTTP 標頭

許可權/功能 請求標頭 回應標頭
原始來源 原始來源 存取控制允許起源
HTTP 方法 存取控制請求方法 存取控制允許方法
請求標頭 存取控制請求頭 存取控制允許標題
回應標頭   存取控制暴露頭
認證   存取控制允許憑據
印前檢查緩存回應   存取控制最大年齡

瀏覽器可以索要這些許可權伺服器,在兩種不同方式:簡單 CORS 請求和印前檢查 CORS 要求。

簡單 CORS 請求在這裡是一個簡單的 CORS 請求的示例:

POST http://localhost/WebApiCorsServer/Resources/ HTTP/1.1
Host: localhost
Accept: */*
Origin: http://localhost:55912
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
value1=foo&value2=5

和的反應:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: http://localhost:55912
Content-Length: 27
{"Value1":"foo","Value2":5}

請求是跨起源從 HTTP://localhost:55912 到 HTTP://localhost,並瀏覽器請求來指示調用起源到伺服器中添加起源 HTTP 標頭。 伺服器的回應與訪問-­控制允許起源的回應標頭,該值指示此起源允許。 瀏覽器強制使用伺服器的策略,和 JavaScript 將接收其正常成功回檔。

伺服器可以使用的確切起源值從請求進行回應或的值為"*"表示任何起源允許。 如果伺服器不允許調用起源,然後存取控制允許起源頭只會缺席,並會調用調用 JavaScript 錯誤回檔。

請注意,與簡單 CORS 要求對伺服器的調用仍然被調用。 如果你正在學習關於 CORS,但這種行為是從瀏覽器中建造了一個 < 表單 > 方案中沒有什麼不同,這可以令人驚訝 元素和作正常 POST 請求。 CORS 並不能防止從伺服器 ; 上正在調用的調用 相反,它阻止調用 JavaScript 接收結果。 如果你想要防止調用方調用此伺服器,然後將實現某種形式的授權伺服器代碼 (可能與 [授權] 授權篩選器屬性) 中。

前面的示例中被稱為一個簡單的 CORS 要求,因為來自用戶端的 AJAX 調用的類型是 GET 或 POST ; 內容類型是一個應用程式/x-www-表單-­urlencoded,多部分/格式資料或文本/平原; 並有發送沒有額外的請求標頭。 如果 AJAX 調用是另一種 HTTP 方法、 內容類型是一些其他的值或用戶端想要發送額外的請求標頭,然後請求將審議印前檢查的請求。 印前檢查請求的力學略有不同。

印前檢查 CORS 請求如果一個 AJAX 調用並不是一個簡單的請求,那麼它需要一個印前檢查的 CORS 請求,是簡單地附加 HTTP 要求到伺服器以獲得相應許可權。 此印前檢查的請求由瀏覽器自動取得並使用的選項 HTTP 方法。 如果伺服器成功回應的印前檢查的請求,並授予的許可權,然後瀏覽器將執行實際的 AJAX 調用 JavaScript 試圖使。

如果是性能問題 (和時是不是?),然後此印前檢查請求的結果可以由瀏覽器緩存由印前檢查回應中包括存取控制最大年齡標頭。 此值包含的許可權可以被緩存的秒數。

這裡是一個印前檢查 CORS 請求的示例:

OPTIONS http://localhost/WebApiCorsServer/Resources/1 HTTP/1.1
Host: localhost
Access-Control-Request-Method: PUT
Origin: http://localhost:55912
Access-Control-Request-Headers: content-type
Accept: */*

和印前檢查回應:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:55912
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: content-typeAccess-Control-Max-Age: 600

這裡是實際的 AJAX 請求:

PUT http://localhost/WebApiCorsServer/Resources/1 HTTP/1.1
Host: localhost
Content-Length: 27
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:55912
Content-Type: application/json
{"value1":"foo","value2":5}

和 AJAX 回應:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: http://localhost:55912
Content-Length: 27
{"Value1":"foo","Value2":5}

在此示例中印前檢查的 CORS 請求通知觸發因為放的 HTTP 方法,用戶端需要將發送的內容類型標頭以指示該請求包含應用程式/json。 印前檢查請求 (除了起源) 中的存取控制請求方法和存取控制請求頭請求標頭用於請求的 HTTP 方法和用戶端想要發送的附加標頭檔的類型的許可權。

在伺服器授予許可權 (和設置一個印前檢查緩存持續時間),然後瀏覽器允許實際的 AJAX 調用。 如果伺服器沒有授予任何的許可權請求的功能,然後相應的回應標頭將已經缺席、 AJAX 調用不會做出了和 JavaScript 錯誤回檔將已經改為調用。

前面的 HTTP 要求和回應作了使用火狐瀏覽器。 如果你使用互聯網資源管理器,然後你會注意到所請求的附加接受標頭檔。 如果你使用 Chrome,你會看到接受和另外要求的起源。 有趣的是,你不會看到接受或起源在訪問-控制-­允許-標題,作為規範說他們隱含的則可以省略 (其中 Web API 不會)。 它是辯論的點,如果原籍國和接受實際上需要請求,但鑒於這些瀏覽器今天工作的方式,您的 Web API CORS 策略將最有可能需要將它們包括。 很可惜瀏覽器廠商似乎並不在他們的規範的閱讀中保持一致。

回應標頭很容易給用戶端的許可權來訪問使用存取控制暴露頭回應標頭的回應標頭。 下面是一個示例,它允許調用的 JavaScript 來訪問"欄"自訂回應標頭的 HTTP 回應:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: http://localhost:55912Access-Control-Expose-Headers: bar
bar: a bar value
Content-Length: 27
{"Value1":"foo","Value2":5}

JavaScript 用戶端只是可以使用用戶端代碼 getResponseHeader 函數讀取的值。 下面是一個使用 jQuery 的例子:

$.ajax({
  url: "http://localhost/WebApiCorsServer/Resources/1",
  // other settings omitted
}).done(function (data, status, xhr) {
  var bar = xhr.getResponseHeader("bar");
  alert(bar);
});

憑據和身份驗證可能 CORS 的最混亂方面具有要使用的憑據和身份驗證。 一般情況下,可以與一個 cookie 或授權標頭進行身份驗證與 Web Api (還有其他的方法,但這兩個最常見)。 在正常的瀏覽器活動中,如果其中之一以前成立了,然後瀏覽器將隱式傳遞這些值到伺服器對於後續的請求。 雖然,與跨起源 AJAX,此隱式傳遞的值必須顯式請求在 JavaScript 中 (通過用戶端代碼的 withCredentials 標誌) 和必須顯式允許在該伺服器的 CORS 政策 (通過存取控制允許憑據回應標頭)。

這裡是設置 withCredentials 標誌與 jQuery JavaScript 用戶端的示例:

$.ajax({
  url: "http://localhost/WebApiCorsServer/Resources/1",
  xhrFields: {
    withCredentials: true
  }
  // Other settings omitted
});

WithCredentials 標誌有兩個作用:如果伺服器將發出一個 cookie,瀏覽器可以接受 ; 如果瀏覽器有一個 cookie,它可以向伺服器發送它。

在這裡是允許憑據的 HTTP 回應的示例:

HTTP/1.1 200 OK
Set-Cookie: foo=1379020091825
Access-Control-Allow-Origin: http://localhost:55912
Access-Control-Allow-Credentials: true

存取控制允許憑據回應標頭有兩個作用:如果回應有一個 cookie,瀏覽器可以接受 ; 如果瀏覽器發送 cookie 的請求,JavaScript 用戶端可以接收調用的結果。 換句話說,如果在用戶端設置 withCredentials,然後用戶端將如果只看到成功回檔在 JavaScript 中的伺服器 (在回應) 允許憑據。 如果設置了 withCredentials 和伺服器不允許憑據,用戶端不會獲得結果,將會調用用戶端錯誤回檔。

(例如,使用基本驗證或集成 Windows 身份驗證時) 使用而 cookie 不授權標頭,是適用于同一組的規則和行為。 有關使用憑據和身份驗證頭有趣的注意:伺服器不一定要顯式授予存取控制允許頭 CORS 回應標頭中的授權標頭。

請注意,與存取控制允許憑據 CORS 回應標頭,如果伺服器問題此標頭,然後的萬用字元值"*"不能用於存取控制允許起源。 相反 CORS 規範要求使用顯式的起源。 Web API 框架處理所有這一切給你,但我在這裡提到它因為在調試時你可能會注意到這種行為。

有一個有趣的轉折在此討論的憑據和身份驗證。 此時的描述一直為在瀏覽器中隱式發送憑據的情況。 它是可能的 JavaScript 用戶端顯式發送憑據 (再次,通常通過授權標頭)。 如果這是如此,那麼,沒有上述規則或行為相關的適用的憑據。

對於此方案,客戶會在請求上顯式設置授權標頭並不需要在用戶端上設置 withCredentials。 此標頭將觸發一個印前檢查請求,伺服器就需要允許授權標頭與存取控制允許頭 CORS 回應標頭。 此外,伺服器就不需要發出訪問-控制-­允許憑據 CORS 回應標頭。

下面是該用戶端代碼會是什麼樣子,顯式設置授權標頭:

$.ajax({
  url: "http://localhost/WebApiCorsServer/Resources/1",
  headers: {
    "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3Mi..."
  }
  // Other settings omitted
});

這裡是印前檢查的要求:

OPTIONS http://localhost/WebApiCorsServer/Resources/1 HTTP/1.1
Host: localhost
Access-Control-Request-Method: GET
Origin: http://localhost:55912
Access-Control-Request-Headers: authorization
Accept: */*

這裡是印前檢查的反應:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: authorization

顯式設置授權標頭中的一個標記值是一種更安全身份驗證方法,因為您避免跨網站請求偽造 (CSRF) 攻擊的可能性。 你可以看到這種方法在新的單頁面應用程式 (SPA) 範本在Visual Studio2013年。

現在,您已經看到的 HTTP 一級 CORS 基礎知識,就會把如何使用新的 CORS 框架來發出 Web API 從這些標題顯示你。

CORS 支援在 Web API 2

CORS 支援 Web API 中的是允許定義為 CORS 請求許可權的應用程式的完整框架。 框架圍繞一項政策,允許您指定 CORS 功能允許為任何給定的請求到應用程式的概念。

第一,為了得到 CORS 框架,你必須從 Web API 應用程式 (它們不在預設情況下從任何 Web API 範本Visual Studio2013年中引用) 引用 CORS 圖書館。 Web API CORS 的框架是可通過 NuGet 作為 Microsoft.AspNet.WebApi.Cors 包。 如果您不使用 NuGet,它也是可用的一部分Visual Studio2013 年,你會需要引用兩個程式集:System.Web.Http.Cors.dll 和 System.Web.Cors.dll (這些都位於 C:\Program 檔 (86) \MicrosoftASP.NET我機器上 \ASP.NETWeb 堆疊 5\Packages)。

下一步,表示該策略,Web API 提供了一個名為 EnableCorsAttribute 的自訂屬性類。 此類包含屬性的允許的起源,HTTP 方法,為請求標頭、 回應標頭和憑據是否允許 (該模型的所有細節 CORS 規範前面討論過的)。

最後,為了使 Web API CORS 框架,以處理 CORS 請求,發出適當的 CORS 回應標頭,它必須看看每個請求在應用程式中。 Web API 有一個可擴充性點,這種攔截通過訊息處理常式。 相應地,Web API CORS 框架實現訊息處理常式調用 CorsMessageHandler。 對於 CORS 請求,它會諮詢表示在被調用的方法的屬性的策略,發出適當的 CORS 回應標頭。

EnableCorsAttribute EnableCorsAttribute 類是一個應用程式是如何表達其 CORS 政策。 EnableCorsAttribute 類具有可以接受三個或四個參數的重載建構函式。 (按順序) 的參數為:

  1. 起源允許清單
  2. 允許的請求標頭的清單
  3. 允許的 HTTP 方法的清單
  4. 允許的回應標頭的清單 (可選)

另外還有一個屬性允許憑據 (支援­憑據),另一個用於指定印前檢查緩存持續時間值 (PreflightMaxAge)。

圖 2 顯示通過 EnableCors 屬性應用於控制器上的各個方法的一個示例。 被用於各種 CORS 策略設置的值應匹配的 CORS 請求和回應,前面的示例所示。

圖 2 通過 EnableCors 屬性應用到操作方法

public class ResourcesController : ApiController
{
  [EnableCors("http://localhost:55912", // Origin
              null,                     // Request headers
              "GET",                    // HTTP methods
              "bar",                    // Response headers
              SupportsCredentials=true  // Allow credentials
  )]
  public HttpResponseMessage Get(int id)
  {
    var resp = Request.CreateResponse(HttpStatusCode.NoContent);
    resp.Headers.Add("bar", "a bar value");
    return resp;
  }
  [EnableCors("http://localhost:55912",       // Origin
              "Accept, Origin, Content-Type", // Request headers
              "PUT",                          // HTTP methods
              PreflightMaxAge=600             // Preflight cache duration
  )]
  public HttpResponseMessage Put(Resource data)
  {
    return Request.CreateResponse(HttpStatusCode.OK, data);
  }
  [EnableCors("http://localhost:55912",       // Origin
              "Accept, Origin, Content-Type", // Request headers
              "POST",                         // HTTP methods
              PreflightMaxAge=600             // Preflight cache duration
  )]
  public HttpResponseMessage Post(Resource data)
  {
    return Request.CreateResponse(HttpStatusCode.OK, data);
  }
}

請注意每個建構函式的參數是一個字串。 通過指定一個以逗號分隔的清單表示多個值 (如為允許的請求標頭中指定了圖 2)。 如果您想要允許所有的起源、 請求標頭或 HTTP 方法,您可以使用"*"作為 (你仍然必須顯式的回應標頭) 的值。

除了應用在方法級別的 EnableCors 屬性,還可以應用它在類級別或全球範圍內對該應用程式。 應用該屬性的級別配置 CORS 該級別及其下面的所有請求在您的 Web API 代碼。 所以,例如,如果在方法級別上應用,政策將僅適用于請求為這項行動,而如果在類級別應用,該政策將對該控制器的所有請求的。 最後,如果應用了全球範圍內,該政策將為所有請求。

以下是通過屬性在類級別應用的另一個例子。 在此示例中使用的設置是相當寬容的因為允許的起源、 請求標頭和 HTTP 方法使用萬用字元:

[EnableCors("*", "*", "*")]
public class ResourcesController : ApiController
{
  public HttpResponseMessage Put(Resource data)
  {
    return Request.CreateResponse(HttpStatusCode.OK, data);
  }
  public HttpResponseMessage Post(Resource data)
  {
    return Request.CreateResponse(HttpStatusCode.OK, data);
  }
}

如果在多個位置有一項政策,使用的"最接近"的特性和其他人都將被忽略 (所以優先順序是方法,然後類,然後全球)。 如果您已經應用在較高級別政策,但然後想要排除較低級別的請求,你可以使用另一個屬性類,稱為 DisableCorsAttribute。 此屬性,本質上,是一項政策,允許沒有許可權。

如果您有其他的方法在您不希望允許 CORS 的控制器上,您可以使用兩個選項之一。 第一,您可以顯式在 HTTP 方法清單中,如中所示圖 3。 或者你可以離開萬用字元,但排除與 DisableCors 屬性中,Delete 方法,如中所示圖 4

圖 3 為 HTTP 方法使用顯式值

[EnableCors("*", "*", "PUT, POST")]
public class ResourcesController : ApiController
{
  public HttpResponseMessage Put(Resource data)
  {
    return Request.CreateResponse(HttpStatusCode.OK, data);
  }
  public HttpResponseMessage Post(Resource data)
  {
    return Request.CreateResponse(HttpStatusCode.OK, data);
  }
  // CORS not allowed because DELETE is not in the method list above
  public HttpResponseMessage Delete(int id)
  {
    return Request.CreateResponse(HttpStatusCode.NoContent);
  }
}

圖 4 使用 DisableCors 屬性

[EnableCors("*", "*", "*")]
public class ResourcesController : ApiController
{
  public HttpResponseMessage Put(Resource data)
  {
    return Request.CreateResponse(HttpStatusCode.OK, data);
  }
  public HttpResponseMessage Post(Resource data)
  {
    return Request.CreateResponse(HttpStatusCode.OK, data);
  }
  // CORS not allowed because of the [DisableCors] attribute
  [DisableCors]
  public HttpResponseMessage Delete(int id)
  {
    return Request.CreateResponse(HttpStatusCode.NoContent);
  }
}

CorsMessageHandler CorsMessageHandler 必須啟用 CORS 框架以執行其工作的攔截請求,以評估 CORS 策略併發出 CORS 回應標頭。 啟用訊息處理常式通常是在應用程式的 Web API 配置類通過調用 EnableCors 的擴充方法:

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Other configuration omitted
    config.EnableCors();
  }
}

如果您希望提供一項全球 CORS 政策,則可以給 EnableCors 方法作為參數傳遞 EnableCorsAttribute 類的一個實例。 例如,下面的代碼將會配置全域應用程式內的縱容 CORS 政策:

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Other configuration omitted
    config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
  }
}

如有任何訊息處理常式中,CorsMessageHandler 或者可以註冊的每個路由而不是在全球範圍內。

所以這是它為基本,"外框"CORS 框架ASP.NETWeb API 2 中。 框架的一大優點就是它是可擴展的更有活力的情況下,我們看看下一步。

自訂策略

它應明顯從起源 (如果不使用萬用字元) 的清單是靜態清單編譯成 Web API 代碼與前面的示例。 儘管這可能在開發期間或特定的情境,它不是足夠如果 (說,從一個資料庫) 動態地確定所需要的起源 (或其他許可權) 的清單。

幸運的是,Web API 的 CORS 框架是可擴展的這樣支援動態清單的起源是很容易。 事實上,框架是政策的如此靈活有兩種常規方法用於自訂生成。

自訂 CORS 策略特性一種方法來啟用動態 CORS 策略是開發一個自訂屬性類,可以從一些資料來源生成策略。 而不是由 Web API 提供的 EnableCorsAttribute 類,可以使用此自訂屬性類。 這種方法簡單,保留細細微性的感覺,是能夠將一個特性應用在特定類和方法 (和不將它應用於其他人),根據需要。

若要實現此方法,您只需生成類似于現有的 EnableCorsAttribute 類的自訂屬性。 主要重點是的 ICorsPolicyProvider 介面,負責創建實例的 CorsPolicy 為任何給定的請求。 圖 5 包含一個示例。

圖 5 自訂 CORS 策略屬性

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
                AllowMultiple = false)]
public class EnableCorsForPaidCustomersAttribute :
  Attribute, ICorsPolicyProvider
{
  public async Task<CorsPolicy> GetCorsPolicyAsync(
    HttpRequestMessage request, CancellationToken cancellationToken)
  {
    var corsRequestContext = request.GetCorsRequestContext();
    var originRequested = corsRequestContext.Origin;
    if (await IsOriginFromAPaidCustomer(originRequested))
    {
      // Grant CORS request
      var policy = new CorsPolicy
      {
        AllowAnyHeader = true,
        AllowAnyMethod = true,
      };
      policy.Origins.Add(originRequested);
      return policy;
    }
    else
    {
      // Reject CORS request
      return null;
    }
  }
  private async Task<bool> IsOriginFromAPaidCustomer(
    string originRequested)
  {
    // Do database look up here to determine if origin should be allowed
    return true;
  }
}

CorsPolicy 類具有表示要授予的 CORS 許可權的所有屬性。 在這裡使用的值只是一個例子,但據推測他們可能會動態填充從資料庫查詢 (或任何其他來源)。

自訂策略提供程式工廠建築動態的 CORS 政策的第二個一般做法是創建自訂策略提供程式工廠。 這是 CORS 框架,用於獲取當前請求的策略提供程式的片斷。 預設實現從 Web API 使用的自訂屬性探索策略提供程式 (如你看到的早些時候,屬性類本身是策略提供程式)。 這是另一個可插拔的 CORS 框架,和如果你想使用一種方法為政策,只能自訂屬性,將執行您自己的政策提供程式工廠。

前面介紹的基於屬性的方法提供了對一項政策從請求隱式關聯。 自訂策略提供程式的工廠方法的屬性方法不同,是因為它需要您的執行提供的邏輯以匹配對政策的傳入請求。 這種方法是更粗細微性的因為它是獲得 CORS 政策基本上是集中式的方法。

圖 6 顯示一個自訂策略提供程式工廠可能會是什麼樣子的一個示例。 在此示例中的主要重點是 ICorsPolicyProviderFactory 介面和其 GetCorsPolicyProvider 方法的執行。

圖 6 自訂策略提供程式工廠

public class DynamicPolicyProviderFactory : ICorsPolicyProviderFactory
{
  public ICorsPolicyProvider GetCorsPolicyProvider(
    HttpRequestMessage request)
  {
    var route = request.GetRouteData();
    var controller = (string)route.Values["controller"];
    var corsRequestContext = request.GetCorsRequestContext();
    var originRequested = corsRequestContext.Origin;
    var policy = GetPolicyForControllerAndOrigin(
      controller, originRequested);
    return new CustomPolicyProvider(policy);
  }
  private CorsPolicy GetPolicyForControllerAndOrigin(
   string controller, string originRequested)
  {
    // Do database lookup to determine if the controller is allowed for
    // the origin and create CorsPolicy if it is (otherwise return null)
    var policy = new CorsPolicy();
    policy.Origins.Add(originRequested);
    policy.Methods.Add("GET");
    return policy;
  }
}
public class CustomPolicyProvider : ICorsPolicyProvider
{
  CorsPolicy policy;
  public CustomPolicyProvider(CorsPolicy policy)
  {
    this.policy = policy;
  }
  public Task<CorsPolicy> GetCorsPolicyAsync(
    HttpRequestMessage request, CancellationToken cancellationToken)
  {
    return Task.FromResult(this.policy);
  }
}

在這種方法的主要區別是它是完全由要確定從傳入請求策略的實現。 在圖 6,在控制器和起源可用於資料庫中查詢的策略值。 同樣,這種方法是最靈活的但它可能需要更多的工作來確定從請求策略。

若要使用自訂策略提供程式工廠,您必須註冊它與 Web API 通過 Web API 配置中的 SetCorsPolicyProviderFactory 擴充方法:

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Other configuration omitted
    config.EnableCors();
    config.SetCorsPolicyProviderFactory(
      new DynamicPolicyProviderFactory());
  }
}

社區行動中的貢獻

ASP.NETWeb API 是一個開源框架,更大的開放源碼框架組的一部分集體稱為ASP.NETWeb 堆疊,其中也包括 MVC、 網頁和其他人。

這些框架用於生成ASP.NET平臺,由 microsoftASP.NET團隊策劃。 作為策展人的開源平臺,ASP.NET團隊歡迎社區的貢獻,並跨起源資源分享 (CORS) 執行 Web API 中的是一種貢獻。

它最初是由布羅克 · 艾倫作為 thinktecture IdentityModel 安全庫的一部分 (thinktecture.github.io)。

調試 CORS

幾種技巧會想到要調試 CORS 如果 (和時) 您跨起源的 AJAX 調用不工作。

用戶端調試的一種辦法就是使用您的 HTTP 調試器的選擇 (例如,提琴手) 並檢查是否所有的 HTTP 要求。 武裝與較早前的 CORS 規範詳細資訊搜集到的知識,你可以進行通常排序出為什麼特定的 AJAX 請求並不被授予許可權通過檢查 CORS HTTP 標頭 (或沒有)。

另一種方法是使用您的瀏覽器 F12 開發人員工具。 在現代瀏覽器中的主控台視窗提供了一個有用的錯誤訊息當 AJAX 調用時由於對 CORS 失敗。

伺服器端 CORS 框架本身提供了詳細的跟蹤消息使用 Web API 的跟蹤功能。 只要 ITraceWriter 註冊的 Web API,CORS 框架將發出消息與選定的策略提供程式、 使用的政策和排放的 CORS HTTP 標頭資訊。 Web API 跟蹤的詳細資訊,請參閱 MSDN 上的 Web API 文檔。

高度請求的功能

CORS 已有些時間了,高度請求的功能,最後它建立在對 Web API。 這篇文章多地側重 CORS 本身的細節但這是在執行和調試 CORS 至關重要的知識。 具備了這方面的知識,你應該能夠輕鬆地利用 CORS 支援在 Web API 允許跨起源調用您的應用程式中。

Brock Allen 是專門在 Microsoft.NET 框架中,Web 開發和基於 Web 的安全顧問。他也是教練培訓公司 DevelopMentor,thinktecture GmbH 的協理顧問 & 有限公司 公斤,貢獻者 thinktecture 打開原始程式碼管理的專案和ASP.NET平臺做出了貢獻。你可以與他聯繫他的 Web 網站, brockallen.com,或電子郵件與他在 brockallen@gmail.com

衷心感谢以下技术专家对本文的审阅:姚煥林 (Microsoft)
姚黃林 (yaohuang@microsoft.com) 是ASP.NETWeb API 團隊在微軟的軟體發展人員。 他曾在許多元件的.NET 框架,包括ASP.NET、 Windows 通信基礎 (WCF) 和 Windows 工作流基礎 (WF)。