一般的基于浏览器跨域的主要解决方法有这么几种: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(){}) 观察请求状态。