搜尋
首頁web前端js教程js實作跨域的4種實用方法原理分析_javascript技巧

什麼是js跨域吶?

js跨域是指透過js在不同的域之間進行數據傳輸或通信,例如用ajax向一個不同的域請求數據,或者透過js獲取頁面中不同域的框架中(iframe)的數據。只要協定、網域、連接埠有任何一個不同,都被當作是不同的網域。

要解決跨域的問題,我們可以使用以下幾種方法:

一、透過jsonp跨域

在js中,我們直接用XMLHttpRequest請求不同域上的資料時,是不行的。但是,在頁面上引入不同網域上的js腳本檔案卻是可以的,jsonp正是利用這個特性來實現的。

例如,有個a.html頁面,它裡面的程式碼需要利用ajax取得一個不同網域上的json數據,假設這個json資料位址是http://example.com/data. php,那麼a.html中的程式碼就可以這樣:

我們看到取得資料的位址後面還有一個callback參數,照慣例是用這個參數名,但是你用其他的也一樣。當然如果取得資料的jsonp位址頁面不是你自己能控制的,就得按照提供資料的那一方的規定格式來操作了。

因為是當做一個js檔案來引入的,所以http://example.com/data.php回傳的必須是一個能執行的js文件,所以這個頁面的php程式碼可能是這樣的:

最終那個頁面輸出的結果是:

所以透過http://example.com/data.php?callback=dosomething得到的js文件,就是我們之前定義的dosomething函數,並且它的參數就是我們需要的json數據,這樣我們就跨域獲得了我們需要的數據。

這樣jsonp的原理就很清楚了,透過script標籤引入一個js文件,這個js文件載入成功後會執行我們在url參數中指定的函數,並且會把我們需要的json資料作為參數傳入。所以jsonp是需要伺服器端的頁面進行對應的配合的。

知道jsonp跨域的原理後我們就可以用js動態產生script標籤來進行跨域操作了,而不用特意的手動的書寫那些script標籤。如果你的頁面使用jquery,那麼透過它封裝的方法就能很方便的來進行jsonp操作了。

原理是一樣的,只不過我們不需要手動的插入script標籤以及定義回掉函數。 jquery會自動產生一個全域函數來取代callback=?中的問號,之後取得到資料後又會自動銷毀,其實就是起一個臨時代理函數的作用。 $.getJSON方法會自動判斷是否跨域,不跨域的話,就呼叫普通的ajax方法;跨域的話,則會以非同步載入js檔案的形式來呼叫jsonp的回呼函數。

2、透過修改document.domain來跨子域

瀏覽器都有一個同源策略,其限制之一就是第一種方法中我們說的不能透過ajax的方法去請求不同來源中的文件。 它的第二個限制是瀏覽器中不同域的框架之間是不能進行js的交互操作的。有一點需要說明,不同的框架之間(父子或同輩),是能夠獲取到彼此的window對象的,但蛋疼的是你卻不能使用獲取到的window對象的屬性和方法(html5中的postMessage方法是一個例外,還有些瀏覽器例如ie6也可以使用top、parent等少數幾個屬性),總之,你可以當做是只能獲取到一個幾乎無用的window對象。例如,有一個頁面,它的位址是http://www.example.com/a.html  , 在這個頁面裡面有一個iframe,它的src是http://example.com/b.html, 很顯然,這個頁面與它裡面的iframe框架是不同域的,所以我們是無法透過在頁面中書寫js程式碼來取得iframe中的東西的:

這時候,document.domain就可以派上用場了,我們只要把http://www.example.com/a.html http://example.com/b.html這兩個頁面的document.domain都設為相同的網域就可以了。但要注意的是,document.domain的設定是有限制的,我們只能把document.domain設定成自身或更高一級的父域,而主域必須相同。例如:a.b.example.com 中某文檔的document.domain 可以設成a.b.example.com、b.example.com 、example.com中的任一個,但是不可以設成c.a.b.example.com,因為這是當前域的子域,也不可以設成baidu.com,因為主域已經不相同了。

在頁面 http://www.example.com/a.html 設定document.domain:

在頁面 http://example.com/b.html 中也設定document.domain,而且這也是必須的,雖然這個文件的domain就是example.com ,但是還是必須顯示的設定document.domain的值:

這樣我們就可以透過js存取到iframe中的各種屬性和物件了。

不過如果你想在http://www.example.com/a.html 頁面中透過ajax直接要求http://example.com/ b.html 頁面,即使你設定了相同的document.domain還是不行的,所以修改document.domain的方法只適用於不同子網域的框架間的互動。如果你想透過ajax的方法去與不同子網域的頁面交互,除了使用jsonp的方法外,還可以用一個隱藏的iframe來做一個代理。原理就是讓這個iframe載入一個與你想要透過ajax取得資料的目標頁面處在相同的網域的頁面,所以這個iframe中的頁面是可以正常使用ajax去取得你要的資料的,然後就是透過我們剛剛講得修改document.domain的方法,讓我們能透過js完全控制這個iframe,這樣我們就可以讓iframe去發送ajax請求,然後收到的資料我們也可以獲得了。

 3、使用window.name來進行跨域

window物件有name屬性,該屬性有個特徵:即在一個視窗(window)的生命週期內,視窗載入的所有的頁面都是共享一個window.name的,每個頁面對window. name都有讀寫的權限,window.name是持久存在一個視窗載入過的所有頁面中的,並不會因為新頁面的載入而重置。

例如:有一個頁a.html,它裡面有這樣的程式碼:

再看b.html頁面的程式碼:

a.html頁面載入後3秒,跳到了b.html頁面,結果為:

我們看到在b.html頁面上成功取得到了它的上一個頁面a.html給window.name設定的值。如果在之後所有載入的頁面都沒對window.name進行修改的話,那麼所有這些頁面取得到的window.name的值都是a.html頁面設定的那個值。當然,如果有需要,其中的任何一個頁面都可以對window.name的值進行修改。注意,window.name的值只能是字串的形式,這個字串的大小最大能允許2M左右甚至更大的一個容量,取決於不同的瀏覽器,但一般是夠用了。

上面的例子中,我們用到的頁面a.html和b.html是處於同一個域的,但是即使a.html與b.html處於不同的域中,上述結論同樣是適用的,這也正是利用window.name進行跨域的原理。

下面就來看看具體是怎麼樣透過window.name來跨域取得資料的。還是舉例說明。

例如有一個www.example.com/a.html頁,需要透過a.html頁面裡的js來取得另一個位於不同網域上的頁面www.jb51.net/data.html裡的資料。

data.html頁面裡的程式碼很簡單,就是給目前的window.name設定一個a.html頁面想要得到的資料值。 data.html裡的程式碼:

那麼在a.html頁面中,我們要怎麼把data.html頁面載入進來呢?顯然我們不能直接在a.html頁面中透過改變window.location來載入data.html頁面,因為我們想要即使a.html頁面不跳轉也能得到data.html裡的資料。答案就是在a.html頁面中使用一個隱藏的iframe來充當一個中間人角色,由iframe去獲取data.html的數據,然後a.html再去得到iframe獲取到的數據。

充當中間人的iframe想要取得到data.html的透過window.name設定的數據,只需要把這個iframe的src設為www.jb51.net/data.html 就行了。然後a.html想要得到iframe所取得的數據,也就是想要得到iframe的window.name的值,還必須把這個iframe的src設為跟a.html頁面同一個域才行,不然根據前面講的同源策略,a.html是不能存取到iframe裡的window.name屬性的。這就是整個跨域過程。

看下a.html頁面的程式碼:

上面的程式碼只是最簡單的原理演示程式碼,你可以對使用js封裝上面的過程,例如動態的創建iframe,動態的註冊各種事件等等,當然為了安全,獲取完數據後,還可以銷毀作為代理的iframe。網路上也有很多類似的現成程式碼,有興趣的可以去找一下。

透過window.name來進行跨域,就是這樣子的。

4、使用HTML5中新引進的window.postMessage方法來跨域傳送資料

window.postMessage(message,targetOrigin)  方法是html5新引進的特性,可以使用它來向其它的window物件發送訊息,無論這個window物件是屬於同源或不同來源,目前IE8 、FireFox、Chrome、 Opera等瀏覽器都已經支援window.postMessage方法。

呼叫postMessage方法的window對像是指要接收訊息的那一個window對象,該方法的第一個參數message為要傳送的訊息,型別只能為字串;第二個參數targetOrigin用來限定接收訊息的那個window物件所在的域,如果不想限定域,可以使用通配符*  。

需要接收訊息的window對象,可是透過監聽自身的message事件來取得傳過來的訊息,訊息內容儲存在該事件對象的data屬性中。

上面所說的向其他window物件發送訊息,其實就是指一個頁面有幾個框架的那種情況,因為每個框架都有一個window物件。在討論第二種方法的時候,我們說過,不同域的框架間是可以取得到對方的window物件的,而且也可以使用window.postMessage這個方法。下面看一個簡單的範例,有兩個頁面

 

我們運行a頁面後得到的結果:

我們看到b頁面成功的收到了訊息。

使用postMessage來跨域傳送資料還是比較直覺和方便的,但是缺點是IE6、IE7不支持,所以用不用還得根據實際需要來決定。

除了以上幾種方法外,還有flash、在伺服器上設定代理頁面等跨域方式,這裡就不做介紹了。

以上四種方法,可以依照專案的實際情況來進行選擇應用,希望這篇文章對大家的學習有所幫助。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript數據類型:瀏覽器和nodejs之間是否有區別?JavaScript數據類型:瀏覽器和nodejs之間是否有區別?May 14, 2025 am 12:15 AM

JavaScript核心數據類型在瀏覽器和Node.js中一致,但處理方式和額外類型有所不同。 1)全局對像在瀏覽器中為window,在Node.js中為global。 2)Node.js獨有Buffer對象,用於處理二進制數據。 3)性能和時間處理在兩者間也有差異,需根據環境調整代碼。

JavaScript評論:使用//和 / * * / * / * /JavaScript評論:使用//和 / * * / * / * /May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript:開發人員的比較分析Python vs. JavaScript:開發人員的比較分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

Python vs. JavaScript:選擇合適的工具Python vs. JavaScript:選擇合適的工具May 08, 2025 am 12:10 AM

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript:了解每個的優勢Python和JavaScript:了解每個的優勢May 06, 2025 am 12:15 AM

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

JavaScript的核心:它是在C還是C上構建的?JavaScript的核心:它是在C還是C上構建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用