一般的基於瀏覽器跨域的主要解決方法有這么幾種:1.JSONP 2.IFrame方式 3.通過flash實現 4.CORS跨域資源共享 ,這里我們主要關注的是在MVC里面的CORS跨域,其余的方式大家可以在網上找到相關的知識看一下。
- CORS的原理:
- CORS瀏覽器支持情況如下圖:


一般的針對ASP.NET MVC,cors跨域訪問,只需要在web.config中添加如下的內容即可
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
但是這種全局設置存在局限性,因為你無法有選擇性的設置可以跨域訪問你本站的站點,所以就想到能不能通過特性標記控制器,或者標記控制器中的方法來設置跨域訪問權限。
比如如下的方式
[ControllerAllowOrigin(AllowSites=new string[] { "aa.com" ,"bb.com"})]
public class TestController
{
}
這樣你可以設置aa.com,bb.com跨域請求你站點TestController里面的任何數據接口方法
或者是如下方式:
public class TestController
{
[ActionAllowOrigin(AllowSites=new string[] { "aa.com" ,"bb.com"})]
public JsonResult Test()
{
}
}
設置aa.com,bb.com只能跨域請求你站點里面的TestController中的Test方法。
這樣的話,我們控制起來就更加靈活方便,允許跨域訪問本站的,在AllowSites里面添加地址就行了。
1. 基於控制器的跨域訪問設置,這邊我定義了一個ControllerAllowOriginAttribute,繼承於AuthorizeAttribute
代碼如下:
public class ControllerAllowOriginAttribute : AuthorizeAttribute
{
public string[] AllowSites { get; set; }
public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
AllowOriginAttribute.onExcute(filterContext, AllowSites);
}
}
2.基於方法的跨域訪問設置,我定義了一個ActionAllowOriginAttribute,繼承於ActionFilterAttribute,
代碼如下:
public class ActionAllowOriginAttribute : ActionFilterAttribute
{
public string[] AllowSites { get; set; }
public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
{
AllowOriginAttribute.onExcute(filterContext, AllowSites);
base.OnActionExecuting(filterContext);
}
}
核心代碼其實很簡單,就這么幾行:
public class AllowOriginAttribute
{
public static void onExcute(ControllerContext context, string[] AllowSites)
{
var origin = context.HttpContext.Request.Headers["Origin"];
Action action = () =>
{
context.HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", origin);
};
if (AllowSites != null && AllowSites.Any())
{
if (AllowSites.Contains(origin))
{
action();
}
}
}
}
其中設置跨域訪問權限的代碼就是這一段HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", origin);
完整的代碼如下:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace IocTEST.Common { public class AllowOriginAttribute { public static void onExcute(ControllerContext context, string[] AllowSites) { var origin = context.HttpContext.Request.Headers["Origin"]; Action action = () => { context.HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", origin); }; if (AllowSites != null && AllowSites.Any()) { if (AllowSites.Contains(origin)) { action(); } } } } public class ActionAllowOriginAttribute : ActionFilterAttribute { public string[] AllowSites { get; set; } public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext) { AllowOriginAttribute.onExcute(filterContext, AllowSites); base.OnActionExecuting(filterContext); } } public class ControllerAllowOriginAttribute : AuthorizeAttribute { public string[] AllowSites { get; set; } public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext) { AllowOriginAttribute.onExcute(filterContext, AllowSites); } } }
調用方式
[ControllerAllowOrigin(AllowSites = new string[] { "http://www.cnblogs.com" })]
public class HomeController : Controller
{
public JsonResult Test()
{
return Json(new { name = "aaa" }, JsonRequestBehavior.AllowGet);
}
}
public class HomeController : Controller
{
[ActionAllowOrigin(AllowSites = new string[] { "http://www.cnbeta.com" })]
public JsonResult Test()
{
return Json(new { name = "aaa" }, JsonRequestBehavior.AllowGet);
}
}
測試的時候,可以將需要跨域訪問你本地localhost站點的網站打開,然后F12打開firebug,在console里面輸入$.post('http://localhost:80/',{},function(){})或者
$.get('http://localhost:80/',{},function(){}) 觀察請求狀態。