前言:上篇總結了下WebApi的接口測試工具的使用,這篇接着來看看WebAPI的另外一個常見問題:跨域問題。本篇主要從實例的角度分享下CORS解決跨域問題一些細節。css
WebApi系列文章html
同源策略:出於安全考慮,瀏覽器會限制腳本中發起的跨站請求,瀏覽器要求JavaScript或Cookie只能訪問同域下的內容。jquery
正是因爲這個緣由,咱們不一樣項目之間的調用就會被瀏覽器阻止。好比咱們最多見的場景:WebApi做爲數據服務層,它是一個單獨的項目,咱們的MVC項目做爲Web的顯示層,這個時候咱們的MVC裏面就須要調用WebApi裏面的接口取數據展示在頁面上。由於咱們的WebApi和MVC是兩個不一樣的項目,因此運行起來以後就存在上面說的跨域的問題。web
CORS全稱Cross-Origin Resource Sharing,中文全稱跨域資源共享。它解決跨域問題的原理是經過向http的請求報文和響應報文裏面加入相應的標識告訴瀏覽器它能訪問哪些域名的請求。好比咱們向響應報文裏面增長這個Access-Control-Allow-Origin:http://localhost:8081,就表示支持http://localhost:8081裏面的全部請求訪問系統資源。其餘更多的應用咱們就不一一列舉,能夠去網上找找。ajax
下面我就結合一個簡單的實例來講明下如何使用CORS解決WebApi的跨域問題。bootstrap
咱們新建兩個項目,一個WebApi項目(下圖中WebApiCORS),一個MVC項目(下圖中Web)。WebApi項目負責提供接口服務,MVC項目負責頁面呈現。以下:api
其中,Web與WebApiCORS端口號分別爲「27239」和「27221」。Web項目須要從WebApiCORSS項目裏面取數據,很顯然,兩個項目端口不一樣,因此並不一樣源,若是使用常規的調用方法確定存在一個跨域的問題。跨域
簡單介紹下測試代碼,Web裏面有一個HomeController瀏覽器
public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } }
對應的Index.cshtml安全
<html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <script src="~/Content/jquery-1.9.1.js"></script> <link href="~/Content/bootstrap/css/bootstrap.css" rel="stylesheet" /> <script src="~/Content/bootstrap/js/bootstrap.js"></script> <script src="~/Scripts/Home/Index.js"></script> </head> <body> 測試結果:<div id="div_test"> </div> </body> </html>
Index.js文件
var ApiUrl = "http://localhost:27221/"; $(function () { $.ajax({ type: "get", url: ApiUrl + "api/Charging/GetAllChargingData", data: {}, success: function (data, status) { if (status == "success") { $("#div_test").html(data); } }, error: function (e) { $("#div_test").html("Error"); }, complete: function () { } }); });
WebApiCORS項目裏面有一個測試的WebApi服務ChargingController
public class ChargingController : ApiController { /// <summary> /// 獲得全部數據 /// </summary> /// <returns>返回數據</returns> [HttpGet] public string GetAllChargingData() { return "Success"; } }
配置WebApi的路由規則爲經過action調用。WebApiConfig.cs文件
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
IE瀏覽器:
谷歌瀏覽器:
這個結果另博主也很吃驚,不作任何跨域處理,IE十、IE11居然能夠直接請求數據成功,而一樣的代碼IE八、IE九、谷歌瀏覽器卻不能跨域訪問。此緣由有待查找,應該是微軟動了什麼手腳。
首先介紹下CORS如何使用,在WebApiCORS項目上面使用Nuget搜索「microsoft.aspnet.webapi.cors」,安裝第一個
而後在App_Start文件夾下面的WebApiConfig.cs文件夾配置跨域
public static class WebApiConfig { public static void Register(HttpConfiguration config) { //跨域配置 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
咱們暫定三個「*」號,固然,在項目中使用的時候通常須要指定對哪一個域名能夠跨域、跨域的操做有哪些等等。這個在下面介紹。
IE十、IE11
谷歌瀏覽器
IE八、IE9
這個時候又有新問題了,怎麼回事呢?我都已經設置跨域了呀,怎麼IE八、9仍是不行呢?這個時候就有必要說說CORS的瀏覽器支持問題了。網上處處都能搜到這張圖:
上圖描述了CORS的瀏覽器支持狀況,能夠看到IE八、9是部分支持的。網上說的解決方案都是Internet Explorer 8 、9使用 XDomainRequest 對象實現CORS。是否是有這麼複雜?因而博主各類百度尋找解決方案。最後發如今調用處指定 jQuery.support.cors = true; 這一句就能解決IE八、9的問題了。具體是在Index.js裏面
jQuery.support.cors = true; var ApiUrl = "http://localhost:27221/"; $(function () { $.ajax({ type: "get", url: ApiUrl + "api/Charging/GetAllChargingData", data: {}, success: function (data, status) { if (status == "success") { $("#div_test").html(data); } }, error: function (e) { $("#div_test").html("Error"); }, complete: function () { } }); });
這句話的意思就是指定瀏覽器支持跨域。原來IE9以上版本的瀏覽器、谷歌、火狐等都默認支持跨域,而IE八、9卻默認不支持跨域,須要咱們指定一下。你能夠在你的瀏覽器裏面打印jQuery.support.cors看看。這樣設置以後是否能解決問題呢?咱們來看效果:
問題完美解決。至於網上說的CORS對IE八、9的解決方案XDomainRequest是怎麼回事,有待實例驗證。
上文咱們使用
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
這一句解決了跨域問題,上面說了,這種*號是不安全的。由於它表示只要別人知道了你的請求url,任何請求均可以訪問到你的資源。這是至關危險的。因此須要咱們作一些配置,限制訪問權限。好比咱們比較常見的作法以下:
配置方法1、在Web.Config裏面(PS:這兩張圖源自:http://www.cnblogs.com/moretry/p/4154479.html)
而後在WebApiConfig.cs文件的Register方法裏面
配置方法2、若是你只想對某一些api作跨域,能夠直接在API的類上面使用特性標註便可。
[EnableCors(origins: "http://localhost:8081/", headers: "*", methods: "GET,POST,PUT,DELETE")] public class ChargingController : ApiController { /// <summary> /// 獲得全部數據 /// </summary> /// <returns>返回數據</returns> [HttpGet] public string GetAllChargingData() { return "Success"; } }
以上就是一個簡單的CORS解決WebApi跨域問題的實例,因爲博主使用WebApi的時間並不長,因此不少理論觀點未必成熟,若是有說的不對的,歡迎指出。博主在此多謝啦。