MVC跨域CORS擴展

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

      

  •  CORS的原理:
     CORS定義一種跨域訪問的機制,可以讓AJAX實現跨域訪問。CORS 允許一個域上的網絡應用向另一個域提交跨域 AJAX 請求。實現此功能非常簡單,只需由服務器發送一個響應標頭即可。
      context.HttpContext.Response.AppendHeader("Access-Control-Allow-Origin", origin);
  • CORS瀏覽器支持情況如下圖:
       
     
        也就是說除了IE8以下版本的瀏覽器不支持,其餘的基於W3c標準的大部分都是支持的。
   

一般的針對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(){})  觀察請求狀態。

發佈了22 篇原創文章 · 獲贊 18 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章