Ajax跨域問題

一個衆所周知的問題,Ajax直接請求普通文件存在跨域無權限訪問的問題。解決方法有JSONP,Flash等等。json

JSONP

咱們發現,Web頁面上調用js文件時不受是否跨域的影響,凡是擁有"src"這個屬性的標籤都擁有跨域的能力,好比<script>、<img>、<iframe>。那就是說若是要跨域訪問數據,就服務端只能把數據放在js格式的文件裏。恰巧咱們知道JSON能夠簡潔的描述複雜數據,並且JSON還被js原生支持,因此在客戶端幾乎能夠爲所欲爲的處理這種格式的數據。而後客戶端就能夠經過與調用腳本如出一轍的方式,來調用跨域服務器上動態生成的js格式文件。客戶端在對JSON文件調用成功以後,也就得到了本身所需的數據。這就造成了JSONP的基本概念。容許用戶傳遞一個callback參數給服務端,而後服務端返回數據時會將這個callback參數做爲函數名來包裹住JSON數據,這樣客戶端就能夠隨意定製本身的函數來自動處理返回數據了。

jQuery支持JSONP的調用。在另外的一個域名中指定好回調函數名稱,就能夠用下面的形式來就加載JSON數據。
url?callback=?
jQuery.getJSON(url + "&callback=?", function(data)  {  
  alert(data.a + data.b);  
});
服務端固然也要提供JSONP的支持,其實只要提供讀寫callback這個params就能夠了。跨域

跨域資源共享(CORS)

Cross-Origin Resource Sharing (CORS) 是W3c工做草案,它定義了在跨域訪問資源時瀏覽器和服務器之間如何通訊。CORS背後的基本思想是使用自定義的HTTP頭部容許瀏覽器和服務器相互瞭解對方,從而決定請求或響應成功與否。瀏覽器

CORS與JSONP相比,更爲先進、方便和可靠。安全

一、 JSONP只能實現GET請求,而CORS支持全部類型的HTTP請求。
二、 使用CORS,開發者可使用普通的XMLHttpRequest發起請求和得到數據,比起JSONP有更好的錯誤處理。
三、 JSONP主要被老的瀏覽器支持,它們每每不支持CORS,而絕大多數現代瀏覽器都已經支持了CORS。
對一個簡單的請求,沒有自定義頭部,要麼使用GET,要麼使用POST,它的主體是text/plain,請求用一個名叫Orgin的額外的頭部發送。Origin頭部包含請求頁面的頭部(協議,域名,端口),這樣服務器能夠很容易的決定它是否應該提供響應。
服務器端對於CORS的支持,主要就是經過設置Access-Control-Allow-Origin來進行的。
Header set Access-Control-Allow-Origin * 
爲了防止XSS攻擊咱們的服務器, 咱們能夠限制域,好比
Access-Control-Allow-Origin: http://blog.csdn.net
不少服務都已經提供了CORS支持,好比 AWS 支持跨域資源分享功能CORS,向S3上傳不須要代理。服務器

與MVC的集成

利用mvc的filter特性,便可很輕鬆的處理jsonp或者cros跨域支持。首先定義2個filter:mvc

    /// <summary>
    /// 轉換請求爲Jsonp格式返回數據
    /// </summary>
    public class JsonpAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            //判斷是否包含Jsonp 是否來自於Ajax請求
            if (!(filterContext.Result is JsonResult))
            {
                return;
            }
            var rdto = filterContext.Result as JsonResult;
            var text = JsonConvert.SerializeObject(rdto.Data);

            var callback = filterContext.HttpContext.Request["callback"];
            text = callback != null ? callback + "(" + text + ")" : text;
            filterContext.Result = new ContentResult()
            {
                ContentType = "application/json",
                Content = text
            };
        }
    }
    /// <summary>
    /// JSON服務堆棧濾波器屬性(可供網頁端任意調用)
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class CORSAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            //判斷返回類型是不是JsonResult
            if (filterContext.Result is JsonResult)
            {
                var jsonResult = filterContext.Result as JsonResult;
                var context = filterContext.HttpContext;
                var response = context.Response;
                response.ContentType = !string.IsNullOrEmpty(jsonResult.ContentType) ? jsonResult.ContentType : "application/json"; //設置類型爲Json格式
                response.AddHeader("Access-Control-Allow-Origin", "*"); //有安全性問題,可根據實際狀況修改 追加頭,是網頁可以異步調用能夠接收
                if (jsonResult.ContentEncoding != null)
                {
                    response.ContentEncoding = jsonResult.ContentEncoding;  //設置編碼格式,默認爲Json
                }
            }
            base.OnActionExecuted(filterContext);
        }
    }

 在註冊filter的時候,咱們將它加入全局控制器,或者應用在須要轉換的控制器或Action上也能夠。app

ps: 全局過濾器,先添加的,最後被執行。你們留意下全局fiter的執行順序。異步

 參考:http://blog.csdn.net/cloudcraft/article/details/8986798ide

相關文章
相關標籤/搜索