ASP.NET WebAPI 15 CORS

同源策略

首先基於安全的緣由,瀏覽器是存在同源策略這個機制的,同源策略阻止從一個源加載的文檔或腳本獲取或設置另外一個源加載的文檔的屬性。git

對於同源必需要求URL在以下幾個方面相同:github

  1. 網絡協議(http與https不一樣)
  2. 域名
  3. 端口(80與8080不一樣)

 

 

JSONP

JSONP是跨域訪問的一種方法。在web開發中咱們常常會引用第三方的js文件,這個時候咱們會發現瀏覽器並無攔截。JSONP就是利用向網頁中添加script標籤的方式去進行跨域訪問。web

通常處理在處理JSONP的時候會將回調函數名與參數做爲QueryString傳給服務端,服務端再根據上傳的函數名生成js回傳給客戶端。api

因爲採用的是添加script標籤的方式,因此JSONP只能經過GET方法訪問服務器。另外因爲服務端要根據上傳的函數名生成js,因此JSONP方法獲得的並非數據,而是方法的調用。跨域

Demo中我寫了一個JSONP的服務端生成與客戶端調用方法。瀏覽器

 

CORS

對於CORSAccess-Control-Allow-Origin安全

引用System.Web.Http.Cors服務器

經過NuGet管理添加System.Web.Http.Cors,我引用的庫名爲:Microsoft ASP.NET Web API 2.2 Cross-Origin Support網絡

 

引用庫後,首先在WebApiConfig.Register方法中首行,添加一句 config.EnableCors()記得必定要添加到首行。開始我也是添加在末行,但一直運行不成功,花了好半天功夫,才找到是這個問題。這個之後有時間再看看Cors內部的實現原理,按說不該該出現這樣的問題。)。cors

 

public static void Register(HttpConfiguration config) 

 { 

// Web API 配置和服務

config.EnableCors(); 

// Web API 路由

config.MapHttpAttributeRoutes(); 

 

 config.Routes.MapHttpRoute( 

 name: "DefaultApi", 

 routeTemplate: "api/{controller}/{action}/{id}", 

 defaults: new { id = RouteParameter.Optional } 

); 

 } 

 

 

 

 

System.Web.Http.Cors庫對於Cors控制也是經過特性(Attribute)來實現的。System.Web.Http.Cors庫提供了兩個與Cors的特性:EnableCorsAttributeDisableCorsAttribute,這兩個特性都是基於ControllerAction的。

 

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] 

public sealed class DisableCorsAttribute : Attribute, ICorsPolicyProvider

 { 

public DisableCorsAttribute(); 

public Task<System.Web.Cors.CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken); 

 } 

 

 

 

 

 

 

 

 

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] 

public sealed class EnableCorsAttribute : Attribute, ICorsPolicyProvider

 { 

public EnableCorsAttribute(string origins, string headers, string methods); 

public EnableCorsAttribute(string origins, string headers, string methods, string exposedHeaders); 

public IList<string> ExposedHeaders { get; } 

public IList<string> Headers { get; } 

public IList<string> Methods { get; } 

public IList<string> Origins { get; } 

public long PreflightMaxAge { get; set; } 

public bool SupportsCredentials { get; set; } 

 

public Task<System.Web.Cors.CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken); 

 } 

 

 

 

EnableCorsAttributeDisableCorsAttribute都實現了ICorsPolicyProvider接口。但 DisableCorsAttribute沒有別的屬性與構造函數,它的使用場景大體爲當Controller已經被添加EnableCorsAttribute後,爲個別不作CorsAction禁用掉。

EnableCorsAttribute的與響應頭部信息相對應,其對應關係以下:

屬性

頭部信息

備註

Origins

Allow-Control-Allow-Origin

CORS容許的請求域名,用逗號(,)去區他不一樣的域名,如:http://localhost:64299,http://www.baidu.com

對於沒有域名,能夠用星號(*)

Methods

Allow-Control-Allow-Method

CORS容許的請求方法,用法同Origins

Headers

Allow-Control-Allow-Headers

 

ExposedHeaders

Allow-Control-Expose-Header

 

PreflightMaxAge

Allow-Control-Max-Age

 

SupportsCredentials

Allow-Control-Allow-Credentials

 

 

 

 

 

 

仍是IE

 

在測試過程當中我發如今火狐上可以正常運行,但到了IE是就不行了,通過一番查找,發現要在要添加一句話:

jQuery.support.cors = true;

 

但加了這句話後,雖然/api/demo/GetFigureByCors能夠調的,/api/demo/GetFigureNoCors也能夠調用了。到這又鬱悶了,這又是要搞那樣。又通過一番折騰,才發現這個時候jQuery並非用的XMLHttpRequest,而是採用的IE自帶的XDomainRequest組件,而且該組件只支持IE8及以上。

 

 

關於Demo

Demo中出於對同源的規則的考慮,我定義了兩個Web項目:API_15API_15.WebAPI_15中的DemoController分別定義的三個方法GetFigureByJsonPGetFigureNoCorsGetFigureByCors分別用於JSONP,非CorsCors調用。

 

public class DemoController : ApiController

 { 

public HttpResponseMessage GetFigureByJsonP(string callback) 

 { 

StringBuilder result = new StringBuilder(); 

 

 result.Append("callback("); 

 result.Append(JsonConvert.SerializeObject(FigureManager.Figures)); 

 result.Append(")"); 

return new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(result.ToString()) }; 

 } 

 

public IEnumerable<Figure> GetFigureNoCors() 

 { 

return FigureManager.Figures; 

 } 

 

//[EnableCors(origins:"*",headers: "*",methods:"*")]

 [EnableCors(origins: "http://localhost:64299,http://www.baidu.com", headers: "GET,POST", methods: "*")] 

public IEnumerable<Figure> GetFigureByCors() 

 { 

return FigureManager.Figures; 

 } 

 }

 

 

 

 

API_15.Web項目中只定義了一個頁面,經過jQueryAJAX去調用API_15中三個Action

 

 

 

源碼

   

Github: https://github.com/BarlowDu/WebAPI(API_15API_15.Web)

相關文章
相關標籤/搜索