C# WebApi CORS跨域問題解決方案
前言:上篇總結了下WebApi的接口測試工具的使用,這篇接著來看看WebAPI的另一個常見問題:跨域問題。本篇主要從實例的角度分享下CORS解決跨域問題一些細節(jié)。
一、跨域問題的由來
同源策略:出于安全考慮,瀏覽器會限制腳本中發(fā)起的跨站請求,瀏覽器要求JavaScript或Cookie只能訪問同域下的內(nèi)容。
正是由于這個原因,我們不同項目之間的調(diào)用就會被瀏覽器阻止。比如我們最常見的場景:WebApi作為數(shù)據(jù)服務層,它是一個單獨的項目,我們的MVC項目作為Web的顯示層,這個時候我們的MVC里面就需要調(diào)用WebApi里面的接口取數(shù)據(jù)展現(xiàn)在頁面上。因為我們的WebApi和MVC是兩個不同的項目,所以運行起來之后就存在上面說的跨域的問題。
二、跨域問題解決原理
CORS全稱Cross-Origin Resource Sharing,中文全稱跨域資源共享。它解決跨域問題的原理是通過向http的請求報文和響應報文里面加入相應的標識告訴瀏覽器它能訪問哪些域名的請求。比如我們向響應報文里面增加這個Access-Control-Allow-Origin:http://localhost:8081,就表示支持http://localhost:8081里面的所有請求訪問系統(tǒng)資源。其他更多的應用我們就不一一列舉,可以去網(wǎng)上找找。
三、跨域問題解決細節(jié)
下面我就結合一個簡單的實例來說明下如何使用CORS解決WebApi的跨域問題。
1、場景描述
我們新建兩個項目,一個WebApi項目(下圖中WebApiCORS),一個MVC項目(下圖中Web)。WebApi項目負責提供接口服務,MVC項目負責頁面呈現(xiàn)。如下:

其中,Web與WebApiCORS端口號分別為“27239”和“27221”。Web項目需要從WebApiCORSS項目里面取數(shù)據(jù),很顯然,兩個項目端口不同,所以并不同源,如果使用常規(guī)的調(diào)用方法肯定存在一個跨域的問題。
簡單介紹下測試代碼,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="external nofollow" 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>
/// 得到所有數(shù)據(jù)
/// </summary>
/// <returns>返回數(shù)據(jù)</returns>
[HttpGet]
public string GetAllChargingData()
{
return "Success";
}
}
配置WebApi的路由規(guī)則為通過action調(diào)用。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 }
);
}
}
2、場景測試
1)我們不做任何的處理,直接將兩個項目運行起來??葱Ч绾?/p>
IE瀏覽器:

谷歌瀏覽器:

這個結果另博主也很吃驚,不做任何跨域處理,IE10、IE11竟然可以直接請求數(shù)據(jù)成功,而同樣的代碼IE8、IE9、谷歌瀏覽器卻不能跨域訪問。此原因有待查找,應該是微軟動了什么手腳。
2)使用CORS跨域
首先介紹下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 }
);
}
}
我們暫定三個“*”號,當然,在項目中使用的時候一般需要指定對哪個域名可以跨域、跨域的操作有哪些等等。這個在下面介紹。
IE10、IE11

谷歌瀏覽器

IE8、IE9

這個時候又有新問題了,怎么回事呢?我都已經(jīng)設置跨域了呀,怎么IE8、9還是不行呢?這個時候就有必要說說CORS的瀏覽器支持問題了。網(wǎng)上到處都能搜到這張圖:

上圖描述了CORS的瀏覽器支持情況,可以看到IE8、9是部分支持的。網(wǎng)上說的解決方案都是Internet Explorer 8、9使用 XDomainRequest對象實現(xiàn)CORS。是不是有這么復雜?于是博主各種百度尋找解決方案。最后發(fā)現(xiàn)在調(diào)用處指定jQuery.support.cors = true;這一句就能解決IE8、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以上版本的瀏覽器、谷歌、火狐等都默認支持跨域,而IE8、9卻默認不支持跨域,需要我們指定一下。你可以在你的瀏覽器里面打印jQuery.support.cors看看。這樣設置之后是否能解決問題呢?我們來看效果:

問題完美解決。至于網(wǎng)上說的CORS對IE8、9的解決方案XDomainRequest是怎么回事,有待實例驗證。
3)CORS的具體參數(shù)設置。
上文我們使用
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
這一句解決了跨域問題,上面說了,這種*號是不安全的。因為它表示只要別人知道了你的請求url,任何請求都可以訪問到你的資源。這是相當危險的。所以需要我們做一些配置,限制訪問權限。比如我們比較常見的做法如下:
配置方法一、在Web.Config里面

然后在WebApiConfig.cs文件的Register方法里面

配置方法二、如果你只想對某一些api做跨域,可以直接在API的類上面使用特性標注即可。
[EnableCors(origins: "http://localhost:8081/", headers: "*", methods: "GET,POST,PUT,DELETE")]
public class ChargingController : ApiController
{
/// <summary>
/// 得到所有數(shù)據(jù)
/// </summary>
/// <returns>返回數(shù)據(jù)</returns>
[HttpGet]
public string GetAllChargingData()
{
return "Success";
}
}
四、總結
以上就是一個簡單的CORS解決WebApi跨域問題的實例,由于博主使用WebApi的時間并不長,所以很多理論觀點未必成熟,如果有說的不對的,歡迎指出。也希望大家多多支持腳本之家。
相關文章
C#實現(xiàn)的Windows剪貼板監(jiān)視器功能實例【附demo源碼下載】
這篇文章主要介紹了C#實現(xiàn)的Windows剪貼板監(jiān)視器功能,結合實例形式分析了C#實現(xiàn)剪貼板監(jiān)視功能所涉及的相關Windows API函數(shù)與使用技巧,需要的朋友可以參考下2016-08-08
C#實現(xiàn)SQL批量插入數(shù)據(jù)到表的方法
這篇文章主要介紹了C#實現(xiàn)SQL批量插入數(shù)據(jù)到表的方法,涉及C#批量操作SQL的相關技巧,需要的朋友可以參考下2016-04-04
C#以太網(wǎng)Sockets客戶端設計實現(xiàn)
本文主要介紹了C#以太網(wǎng)Sockets客戶端設計實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-02-02
C#中Decimal類型截取保留N位小數(shù)并且不進行四舍五入操作
這篇文章主要介紹了C#中Decimal類型截取保留N位小數(shù)并且不進行四舍五入操作,本文給出需求說明和實現(xiàn)代碼,需要的朋友可以參考下2015-06-06
http圖片上傳安全性問題 根據(jù)ContentType (MIME) 判斷其實不準確、不安全
圖片上傳常用的類型判斷方法有這么幾種---截取擴展名、獲取文件ContentType (MIME) 、讀取byte來判斷(這個什么叫法來著?)。下面由腳本之家小編跟大家分享圖片上傳安全性問題,感興趣的朋友一起看看吧2015-09-09

