1. 程式人生 > >也談跨域資料互動解決方案

也談跨域資料互動解決方案

提醒:本文最後更新於 2677 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

先來句題外話,最開始Ajax應該是用來特指用XMLHttpRequest傳輸資料這門技術,但就像最近大家把一切web新技術都歸到html5名下一樣,現在一切非同步獲取資料的手段都被人稱之為Ajax。

由於JavaScript同源策略的存在,跨域資料互動是個老生常談的話題了。網上相關文章很多,不過隨著時間的推移和瀏覽器的更新,一部分解決方案已經不適用了,同時也出現了一些更好的方法。拋開純伺服器Proxy這種跟前端沒什麼關係的方案不說,這裡簡單總結下常見的其他幾種方式。

JSONP

JSONP是最常見的跨域資料互動的方式,原理是html的script標籤可以載入並執行其他域JS檔案。站點B把要提供的資料作為引數傳給一個站點A定義的全域性函式,站點A引用這個檔案就可以跨域獲取資料了,A站還可以把少量引數放在script標籤的src裡提交給B站。外鏈JS這種方案只支援GET,受IE下url長度不能超過2083個位元組的限制和出於安全考慮,一般不用來提交資料。

有人通過後端Proxy使得這種方式可以獲取任意頁面內容,還增加了對POST的支援,如:

<script type="text/javascript" src="http://www.ajax-cross-domain.com/cgi-bin/ACD/ACD.js?uri=(http://www.google.com)"></script>
<script type="text/javascript">
    alert(ACD.responseText);
</script>
<script type="text/javascript" src="http://www.ajax-cross-domain.com/cgi-bin/ACD/ACD.js?uri=(http://216.92.131.147/dotserv/ACD/runit/post.cgi)&method=post&postdata=(name=fred&
[email protected]
)"
>
</script> <script type="text/javascript"> alert(ACD.responseText); </script>

實際上這個方案是藉助後端把任意頁面輸出為JS變數,後端根據url中相關標識來決定請求方式和引數,並不能解決大資料提交問題。

原生表單+Redirect+Callback

原生的form表單支援提交資料到其他域,我們只需要把form的target指向頁面上的隱藏iframe,那就實現了無重新整理提交,剩下的問題就是怎麼獲取提交後的結果。例如站點A表單提交資料到站點B,通常我們會在站點B處理完請求,重定向到站點A下某個Proxy頁面,並在url帶上引數標識處理結果。接著,A站下的Proxy頁面就可以解析url引數,傳給父頁面的Callback函式來處理了。

Flash

利用flash的URLLoader,也可以輕鬆實現跨域資料互動。只要站點B的跨域策略檔案(crossdomain.xml)中包含了站點A,A站就可以獲取B站的資料,提交資料給B站。我們可以把JS和flash的互動封裝一下,更方便的使用。這裡有一個別人封裝好的版本,使用起來和原生的XMLHttpRequest幾乎一模一樣:

var req;
function callback() {
   if (req.readyState == 4) {
     try {
       if (req.status != 200) {
           alert('error detected 1');
       } else {
         alert("got data: "+req.responseText);
       }
     } catch(e) {
         alert('error detected 2');
     }
   }
}
function test_get() {
  req = new CrossXHR();
  req.onreadystatechange = callback;
  req.open('GET', 'http://www.pliantdev.com/support/test.xml');
  req.send();
}

Iframe+XMLHttpRequest

如果站點B有一個proxy頁面,用原生Ajax(XMLHttpRequest)對B站其他頁面進行各種資料互動,那麼我們在A站用iFrame引入這個proxy頁面,只需要解決iFrame跨域問題就可以了。實際上,如果A和B屬於相同大域,設定兩邊的document.domain為根域名就OK了;如果是完全不同的兩個域,也有許多現成的解決方案,例如經典的window.name。更妙的是,除開IE6、IE7,幾乎所有現代瀏覽器都支援用window.postMessage實現不同iFrame的資料通訊。pmxdr就是這樣一個庫,利用postMessage把資料傳給隱藏的站外iFrame來實現跨域Ajax,libxdr對它進行了進一步的封裝,使之更好用:

var req = new XDR();
req.open("POST", "http://code.eligrey.com/pmxdr/libxdr/demo.php");
req.setRequestHeader("Content-Type", 
    "application/x-www-form-urlencoded");
req.onload = function() {
    alert(this.responseText); // alerts "foo is bar"
};
request.send("foo=bar");

值得注意的是,這種方案只需要在站點B部署一個proxy頁面,其他任意站點都可以通過這個頁面與之互動,不太安全,這一點pmxdr考慮到了,在pmxdr-host.js裡有一個變數alwaysTrustedOrigins,它是一個數組,支援用正則定義允許互動的站點。

終極解決方案:CORS

實際上,除了IE6、IE7,大部分現代瀏覽器已經支援了跨域資源共享(Cross-Origin Resource Sharing,簡稱:CORS)標準,這可謂是跨域Ajax的終極解決方案。有了這個標準,只需要在Response Header里加上這麼一條,就可以輕鬆跨域了:

Access-Control-Allow-Origin: http://hello-world.example

這個header定義允許哪些域跟自己互動,如果定義為*就表示允許任何域,這麼做當然是不推薦的。在除IE之外的標準瀏覽器,這樣就可以跨域Ajax了。對於IE,需要換用新增的XDomainRequest物件來發送請求,其它都類似。另外還有幾個header可以用來設定允許的提交方式等資訊,如果要支援認證或者提交xml等格式的資料給伺服器,則需要預請求,這裡有更多說明。

總結

不同的方案有各自不同的使用場景,誰好誰壞不能一概而論。一般的,跨域獲取資料個人習慣用JSONP,跨域提交資料個人習慣用表單+Callback。隨著現代瀏覽器的普及,原生xhr也可以嘗試下,flash可以作為替補降級用。最後,如果要選用一個封裝了多種跨域實現的庫,可以考慮下Yui3的io元件

本文提到一些元件連結:

--EOF--

提醒:本文最後更新於 2677 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

相關推薦

資料互動解決方案

提醒:本文最後更新於 2677 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 先來句題外話,最開始Ajax應該是用來特指用XMLHttpRequest傳輸資料這門技術,但就像最近大家把一切web新技術都歸到html5名下一樣,現在一切非同步獲取資料的手段都被人稱之為Ajax。 由於Java

PHP Ajax 問題最佳解決方案

ajax 跨域 域名 -c php文件 解決 tle ron 跨域訪問 客戶端 本文通過設置Access-Control-Allow-Origin來實現跨域。 例如:客戶端的域名是client.runoob.com,而請求的域名是server.runoob.com。 如

.net webapi項目問題及解決方案

prot net 方案 ted access 節點 跨域訪問 架構師資料 eth 問題: 1.項目完成,部署到不同的iis版本上,跨域訪問有的通有的不通 解決辦法: 1.將復雜請求改為簡單請求 2.代碼中去掉所有跨域設置,配置中添加或修改節點 <system

關於ajax的一些解決方案

dst control 關於 請求 method request 進行 前端 請求方式 1、JSONP方式解決跨域問題 jsonp解決跨域問題是一個比較古老的方案(實際中不推薦使用),當然,在實際項目中如果要使用JSONP,一般會使用JQ等對JSONP進行了封裝的

Ajax原理及解決方案

一次 變化 mes iframe 實現 type .ajax 一個 min 跨域請求的產生 跨域請求歸根結底是由於瀏覽器的“同源策略”引起的,同源策略指的是域名相同、協議相同、端口相同, 假設有http://www.a.com/test.html,下面的示例 域名不同 h

PHP ajax問題最佳解決方案

var cell clear 一定的 OS 添加 會有 request TP 一、本文通過設置Access-Control-Allow-Origin來實現跨域。 例如:客戶端的域名是client.runoob.com,而請求的域名是server.runoob.com。 如

PHP Ajax 問題最佳解決方案 【摘自菜鳥教程】

set color ray quest origin tty 所有 $origin con PHP Ajax 跨域問題最佳解決方案 分類 編程技術 http://www.runoob.com/w3cnote/php-ajax-cross-border.html 本文

Access to Image at 'file:///Users canvas本地圖片報錯解決方案

本地服務 canvas 解決方案 圖片 報錯 訪問 can 支持 ESS 1、設置跨域 添加跨域條件 crossorigin="anonymous" 前提是後端支持這個圖片跨域 2、上面加了之後還是報錯   如標題所示  

分享訪問的解決方案與基礎分析

什麼是跨域訪問? 由於瀏覽器同源策略,凡是傳送請求url的協議、域名、埠三者之間任意一個與當前頁面地址不同即為跨域。存在跨域的情況: 網路協議不同,如http協議訪問https協議。 埠不同,如80埠訪問8080埠。 域名不同,如qianduanblog.com訪問baidu.com。

.Net平臺下,處理問題CORE解決方案

VS2017 安裝兩個包:Install-PackageMicrosoft.AspNet.WebApi.Cors(如果build不過去還需安裝:Install-Package Microsoft.AspNet.WebApi-IncludePrerelease)  1、 

php 和ajax問題的解決方案

本文通過設定Access-Control-Allow-Origin來實現跨域。 例如:客戶端的域名是client.runoob.com,而請求的域名是server.runoob.com。 如果直接使用ajax訪問,會有以下錯誤: XMLHttpRequest cannot load http://s

JS:1.解決方案之-SpringMVC攔截器

package com.bdqn.utils; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResp

理解及常用解決方案

跨域,相信大家無論是在工作中還是在面試中經常遇到這個問題,常常在網上看到別人所整理的一些方法,看似知道是怎麼回事,但如果沒有動手實踐過,總覺得自己沒有真正的掌握,在這裡,通過自己認真思考整理一些常用的方法。 跨域的產生 不用多講,作為一名前端開發人員,相信大家都知道跨域是因為瀏覽器的同源策略所導致的

Web學習之問題及解決方案

在做前端開發時,我們時常使用ajax與伺服器通訊獲取資源,享受ajax便利的同時,也知道它有限制:跨域安全限制,即同源策略。 同源策略(SOP),核心是確保不同源提供的檔案之間是相互獨立的 預設情況下,XHR物件只能訪問與包含它的頁面處於同一域中的資源,這種限制可以預防某些惡意攻擊,但同

一篇關於ajax問題的解決方案

  這幾天沒事,我有一個好友,讓我幫他做一個機器人對話demo, 我說 看看有沒有時間(其實自己一臉懵逼) 然後百度了一下,發現了一個機器人  -(連線就不弄出來了,可以私底下交流) ,,我是用這個的        

JS請求的解決方案

出現JS跨域請求的原因: 瀏覽器檢測到源的異常 什麼叫做JS跨域: 兩個應用協議,主機地址(域名),埠號。三者有一個不同,則認為他們的域不同。 例如: http:localhost:80/a https:localhost:80/b 此時的a與b的應用協議是不同

到底什麼是?附解決方案

什麼是跨域 要了解跨域,先要說說同源策略。 同源策略是由 Netscape 公司提出的一個著名的安全策略,所有支援 JavaScript 的瀏覽器都會使用這個策略。 所謂同源是指,域名,協議,埠相同。當頁面在執行一個指令碼時會檢查訪問的資源是否同源,如果非同源,那麼

web 專案解決問題終極解決方案

一.跨域問題的由來 二.怎麼就算跨域(同源的定義) 三.常見跨域解決方法 四.總結 一.跨域問題的由來 為什麼會產生這樣一個問題,擺在我們面前呢?? 理解跨域,首先必須要了解同源策略。同源策略是瀏覽器上為安全性考慮實施的非常重要的安全策略。 為了防止某些文件或指令碼載入別

session共享問題解決方案

在討論session跨域共享問題之前,我們首先要了解session做了什麼,沒做到什麼 HTTP是無狀態的,也就是說伺服器不知道誰訪問過他,但是有時候,又需要我們去保留這個狀態比如說使用者的登入資訊,如果每次訪問都要登陸,這個使用者體驗實在是太糟糕了,ses

ajax問題以及解決方案

在工作中,大家應該都遇到過ajax跨域問題,瀏覽器的錯誤如下: XMLHttpRequest cannot load http://目標地址No 'Access-Control-Allow-Origin' header is present on the requested