在做Web开发中,常常会遇到跨域的问题,到目前为止,已经有非常多的跨域解决方案。由于时间有限,本文不会深入。
笔者遇到的问题是Js调用WebAPI中的数据进行跨域的场景。涉及若干跨域方案:
方案1:jsonp+回调
方案2:Microsoft.AspNet.WebApi.Cors提供的跨域属性
方案3:利用ACAO编写自定义Filter实现
一、关于方案一
方案1是同事提出来的,已经经过论证,并且自己研究过,是可行的。本质上是通过script标签动态加载js,还有callback机制。
但是,我个人觉得这个方案有些不足:
-
实现细节复杂,技术复杂性增大了不少,并且不好理解(服务器端、Web前端两头忙活)
-
只支持单向跨域
-
只支持Get,不支持Post等Http请求
-
扩展性不强
-
我在读参考文章时,感觉思路不清晰(至于是作者思路不清晰,还是写作思路不清晰,还是我个人理解能力不到位这个不好说。)
二、关于方案二
首先,我提出了方案2。当时在我看来,这个是比较合适的一个方案,接近完美。但是,它不可行。
原因在于:Microsoft.AspNet.WebApi.Cors的framework版本是4.5,而我们现有项目是4.0。我们的时间有限,几乎没有时间做深入研究。
三、关于方案三
我受方案2的启发,个人实现了方案3。方案3实现的最终效果接近方案2。支持:Global级别、Controller级别、Action级别。
方案三的缺点:因为“Access-Control-Allow-Origin”是HTML5中新增的特性,所以IE10以下浏览器不支持。
代码如下:
using System.Web.Http.Filters; namespace MvcApplication1.CustomFilter { public class CrossSiteAttribute : ActionFilterAttribute { private const string Origin = "Origin"; private const string AccessControlAllowOrigin = "Access-Control-Allow-Origin"; private const string originHeaderdefault = "*"; public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { actionExecutedContext.Response.Headers.Add(AccessControlAllowOrigin, originHeaderdefault); } } }
服务器端代码示例:
[CrossSite] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; }
服务器端只需要把过滤器的标签[CrossSite]写上,服务器端就支持跨域了。省去了Web前端的处理和服务器端回调的处理。
当然,它很容易进行扩展。