JavaScript跨域方法匯總_javascript技巧

來源:互聯網
上載者:User

做Web開發經常需要面對跨域問題,跨域問題的根源是瀏覽器安全中的同源策略,比如說,對於http://www.a.com/1.html來說:

1.http://www.a.com/2.html是同源的;
2.https://www.a.com/2.html是不同源的,原因是協議不同;
3.http://www.a.com:8080/2.html是不同源的,原因是連接埠不同;
4.http://sub.a.com/2.html是不同源的,原因是主機不同。

在瀏覽器中,<script>、<img>、<iframe>和<link>這幾個標籤是可以載入跨域(非同源)的資源的,並且載入的方式其實相當於一次普通的GET請求,唯一不同的是,為了安全起見,瀏覽器不允許這種方式下對載入到的資源的讀寫操作,而只能使用標籤本身應當具備的能力(比如指令碼執行、樣式應用等等)。

最常見的跨域問題是Ajax跨域訪問的問題,預設情況下,跨域的URL是無法通過Ajax訪問的。這裡我記錄我所瞭解到的跨域的方法:

1. 伺服器端代理,這沒有什麼可說的,缺點在於,預設情況下接收Ajax請求的服務端是無法擷取到的用戶端的IP和UA的。

2. iframe,使用iframe其實相當於開了一個新的網頁,具體跨域的方法大致是,域A開啟的母頁面嵌套一個指向域B的iframe,然後提交資料,完成之後,B的服務端可以:

●返回一個302重新導向響應,把結果重新指回A域;
●在此iframe內部再嵌套一個指向A域的iframe。

這兩者都最終實現了跨域的調用,這個方法功能上要比下面介紹到的JSONP更強,因為跨域完畢之後DOM操作和互相之間的JavaScript調用都是沒有問題的,但是也有一些限制,比如結果要以URL參數傳遞,這就意味著在結果資料量很大的時候需要分割傳遞,甚是麻煩;還有一個麻煩是iframe本身帶來的,母頁面和iframe本身的互動本身就有安全性限制。

3. 利用script標籤跨域,這個辦法也很常見,script標籤是可以載入異域的JavaScript並執行的,通過預先設定好的callback函數來實現和母頁面的互動。它有一個大名,叫做JSONP跨域,JSONP是JSON with Padding的略稱。它是一個非官方的協議,明明是載入script,為啥和JSON扯上關係呢?原來就是這個callback函數,對它的使用有一個典型的方式,就是通過JSON來傳參,即將JSON資料填充進回呼函數,這就是JSONP的JSON+Padding的含義。

在互連網上有很多JSONP的服務來提供資料,本質上就是跨域請求,並且在請求URL中指定好callback,比如callback=result,那麼在擷取到這些資料以後,就會自動調用result函數,並且把這些資料以JSON的形式傳進去,例如(搜尋“football”):

http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=football&callback=result

使用JQuery來調用就寫成:

複製代碼 代碼如下:

$.getJSON("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=football&callback=?",function(data){
    //...
});

總的來說,JSONP的跨域方式的局限性在於,只能使用GET請求,並且不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題。

4. Flash跨域:

它會訪問目標網站根目錄下面的crossdomain.xml檔案,根據檔案中的內容來確定是否允許此次跨域訪問:

複製代碼 代碼如下:

<cross-domain-policy>
    <allow-access-from domain="xxx.xxx.com" />
</cross-domain-policy>

5. img標籤也可以使用,這也是一種非常常見的方法,功能上面弱一點,只能發送一個get請求,沒有什麼回調,Google的點擊計數就是這樣確定的。

6. window.PostMessage,這個算是HTML5新加入的為跨域通訊考慮的機制,只有Firefox 3、Safari 4和IE8及之後的版本支援。使用它向其它視窗發送訊息的調用方式如下:

複製代碼 代碼如下:

otherWindow.postMessage(message, targetOrigin);

在接收的視窗,需要設定一個事件處理函數來接收發過來的訊息:
複製代碼 代碼如下:

window.addEventListener("message", receiveMessage, false);
function receiveMessage(event){
    if (event.origin !== "http://example.org:8080")
        return;
}

注意這裡必需要使用訊息的origin和source屬性來驗證寄件者的身份,否則會造成XSS漏洞。

7. Access Control

有一些瀏覽器支援Access-Control-Allow-Origin這樣的回應標頭,比如:

複製代碼 代碼如下:

header("Access-Control-Allow-Origin: http://www.a.com");

就指定了允許對www.a.com跨域訪問。

8. window.name

這個東西其實以前被用作駭客XSS的手段,其本質是,當window的location變化的時候,頁面會重新載入,但是有趣的是,這個window.name居然不發生變化,那麼就可以用它來傳值了。配合iframe,改變幾次iframe的window對象,就完成了實用的跨域資料傳遞。

9. document.domain

這個方式適用於a.example.com和b.example.com這種跨域的通訊,因為二者有一個共有的域,叫做example.com,只要設定document.domain為example.com就可以了,但是如果a.example1.com和b.example2.com之間要通訊,它就沒辦法了。

10. Fragment Identitier Messaging(FIM)

這個方法很有意思,也需要iframe的配合。Fragment Identitier就是URL的井號(#)後面的經常用於錨點定位的部分,這部分的改變不會導致頁面重新整理,母視窗可以隨便訪問iframe的URL,而iframe也可以隨便訪問母視窗的URL,那這二者之間就可以通過改變Fragmement Identitier來實現通訊了。缺點是Fragmement Identitier的改變會產生不必要的記錄,而且也有長度限制;另外,有的瀏覽器不支援onhashchange事件。

11. Cross Frame(CF)

這種方法是上述FIM方法的變種,CF和FIM的本質其實在我的《GWT初體驗》這篇文章裡面都有介紹(只不過是被用來實現曆史和後退功能了),它會動態建立一個不可見的iframe,指向異域,處理完以後,這個iframe的URL中的Fragment Identitier包含了處理結果,供母頁面訪問,而瀏覽器的URL沒有任何變化。

12. Cookie+P3P協議

利用P3P協議下跨域訪問Cookie的特性,來實現跨域訪問,也算一奇招。P3P是W3C公布的一項隱私保護推薦標準,旨在為網上衝浪的Internet使用者提供隱私保護。把Cookie的path設定為“/”,即沒有任何域的限制,這個時候有的瀏覽器下面允許別的URL的頁面來讀取,有的則不允許,這種情況下需要在母頁面響應的頭上面設定P3P的頭:

複製代碼 代碼如下:

P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.