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

js實作跨域的4種實用方法原理分析_javascript技巧

May 16, 2016 pm 03:34 PM

什麼是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

熱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

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1317
25
PHP教程
1268
29
C# 教程
1243
24
JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript:探索網絡語言的多功能性 JavaScript:探索網絡語言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

如何使用Next.js(前端集成)構建多租戶SaaS應用程序 如何使用Next.js(前端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

使用Next.js(後端集成)構建多租戶SaaS應用程序 使用Next.js(後端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

See all articles