常見(jiàn)的javascript跨域通信方法
本文主要介紹幾種常見(jiàn)的javascript跨域通信方法。首先講解一下JSONP。
1、JSONP
JSONP(JSON with Padding)是JSON的一種“使用模式”,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問(wèn)的問(wèn)題。由于同源策略,一般來(lái)說(shuō)位于 server1.example.com 的網(wǎng)頁(yè)無(wú)法與不是 server1.example.com的服務(wù)器溝通,而 HTML 的<script> 元素是一個(gè)例外。利用 <script> 元素的這個(gè)開(kāi)放策略,網(wǎng)頁(yè)可以得到從其他來(lái)源動(dòng)態(tài)產(chǎn)生的 JSON 資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料并不是JSON,而是任意的JavaScript,用 JavaScript 直譯器執(zhí)行而不是用 JSON 解析器解析。
下面我們來(lái)介紹下JSONP的具體實(shí)現(xiàn)。
我們知道,哪怕跨域js文件中的代碼(當(dāng)然指符合web腳本安全策略的),web頁(yè)面也是可以無(wú)條件執(zhí)行的。遠(yuǎn)程服務(wù)器remoteserver.com根目錄下有個(gè)remote.js文件代碼如下:
alert('我是遠(yuǎn)程文件');
本地服務(wù)器localserver.com下有個(gè)jsonp.html頁(yè)面代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript" src="http://remoteserver.com/remote.js"></script> </head> <body> </body> </html>
毫無(wú)疑問(wèn),頁(yè)面將會(huì)彈出一個(gè)提示窗體,顯示跨域調(diào)用成功。
現(xiàn)在我們?cè)趈sonp.html頁(yè)面定義一個(gè)函數(shù),然后在遠(yuǎn)程remote.js中傳入數(shù)據(jù)進(jìn)行調(diào)用。jsonp.html頁(yè)面代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> var localHandler = function(data){ alert('我是本地函數(shù),可以被跨域的remote.js文件調(diào)用,遠(yuǎn)程js帶來(lái)的數(shù)據(jù)是:' + data.result); }; </script> <script type="text/javascript" src="http://remoteserver.com/remote.js"></script> </head> <body> </body> </html>
remote.js文件代碼如下:
localHandler({"result":"我是遠(yuǎn)程js帶來(lái)的數(shù)據(jù)"});
成功運(yùn)行,看來(lái)跨域遠(yuǎn)程獲取數(shù)據(jù)的目的實(shí)現(xiàn)了,但是又一個(gè)問(wèn)題出現(xiàn)了,我怎么讓遠(yuǎn)程js知道它應(yīng)該調(diào)用的本地函數(shù)叫什么名字呢?這時(shí)我們就需要將服務(wù)端提供的js腳本動(dòng)態(tài)生成就行了,調(diào)用者可用通過(guò)傳參告訴服務(wù)端自己需要什么函數(shù),jsonp.html的代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <script type="text/javascript"> // 得到航班信息查詢結(jié)果后的回調(diào)函數(shù) var flightHandler = function(data){ alert('你查詢的航班結(jié)果是:票價(jià) ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 張。'); }; // 提供jsonp服務(wù)的url地址(不管是什么類型的地址,最終生成的返回值都是一段javascript代碼) var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; // 創(chuàng)建script標(biāo)簽,設(shè)置其屬性 var script = document.createElement('script'); script.setAttribute('src', url); // 把script標(biāo)簽加入head,此時(shí)調(diào)用開(kāi)始 document.getElementsByTagName('head')[0].appendChild(script); </script> </head> <body> </body> </html>
這次的代碼變化比較大,不再直接把遠(yuǎn)程js文件寫死,而是編碼實(shí)現(xiàn)動(dòng)態(tài)查詢,而這也正是jsonp客戶端實(shí)現(xiàn)的核心部分,本例中的重點(diǎn)也就在于如何完成jsonp調(diào)用的全過(guò)程。
我們看到調(diào)用的url中傳遞了一個(gè)code參數(shù),告訴服務(wù)器我要查的是CA1998次航班的信息,而callback參數(shù)則告訴服務(wù)器,我的本地回調(diào)函數(shù)叫做flightHandler,所以請(qǐng)把查詢結(jié)果傳入這個(gè)函數(shù)中進(jìn)行調(diào)用。這個(gè)叫做flightResult.aspx的頁(yè)面生成了一段這樣的代碼提供給jsonp.html(服務(wù)端的實(shí)現(xiàn)這里就不演示了,與你選用的語(yǔ)言無(wú)關(guān),說(shuō)到底就是拼接字符串):
flightHandler({ "code": "CA1998", "price": 1780, "tickets": 5 });
傳遞給flightHandler函數(shù)的是一個(gè)json,它描述了航班的基本信息。運(yùn)行一下頁(yè)面,成功彈出提示窗口,jsonp的執(zhí)行全過(guò)程順利完成!
但是JSONP存在一點(diǎn)問(wèn)題,就是由遠(yuǎn)程服務(wù)端負(fù)責(zé)包裝json數(shù)據(jù),并調(diào)用命名函數(shù),這種方式存在安全隱患,在使用JSONP時(shí),必須完全信任服務(wù)端所提供的數(shù)據(jù),惡意腳本就可以直接接管我們的應(yīng)用。所以接下來(lái)我們要介紹一種別的方式,來(lái)避免這種安全隱患。
2、CORS
CORS(Cross OriginResource Sharing,跨源資源共享)實(shí)現(xiàn)了跨源XMLHttpRequests,跨源HTTP請(qǐng)求包括一個(gè)Origin頭部,它為服務(wù)器提供HTTP請(qǐng)求的源信息。頭部由瀏覽器保護(hù),不能被應(yīng)用程序代碼更改。這種方式遠(yuǎn)比評(píng)估外部輸入的方式安全。
以前的ajax只能同源請(qǐng)求,現(xiàn)在通過(guò)XMLHttpRequests二級(jí),可以進(jìn)行跨域請(qǐng)求。假設(shè)我們頁(yè)面或者應(yīng)用已在 http://www.test1.com 上了,而我們打算從 http://www.test2.com 請(qǐng)求提取數(shù)據(jù)。一般情況下,如果我們直接使用 AJAX 來(lái)請(qǐng)求將會(huì)失敗,瀏覽器也會(huì)返回“源不匹配”的錯(cuò)誤,"跨域"也就以此由來(lái)。
利用 CORS,http://www.test2.com 只需添加一個(gè)標(biāo)頭,就可以允許來(lái)自 http://www.test1.com 的請(qǐng)求。php代碼如下:
header("Access-Comtrol-Allow-Origin:*");<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
其中*表示允許任何域向我們的服務(wù)端提交請(qǐng)求。也可以設(shè)置指定的域名,代碼如下:
header("Access-Control-Allow-Origin:http://www.test2.com");
設(shè)置好頭信息之后,其他域就可以進(jìn)行請(qǐng)求了。
使用"跨域資源共享"的前提,是瀏覽器必須支持這個(gè)功能,而且服務(wù)器端必須同意這種"跨域"。如果能夠滿足上面的條件,則代碼的寫法與不跨域的請(qǐng)求完全一樣。
xhr.open('GET', ' http://www.test2.com ');
接下來(lái)介紹另外一種實(shí)時(shí)通信方式:
3、Cross-document messaging
跨文檔信息通信。使用這個(gè)功能,只要獲取到網(wǎng)頁(yè)所在窗口對(duì)象的實(shí)例,不僅同原的web網(wǎng)頁(yè)可以互相通信,也可以實(shí)現(xiàn)跨域通信。要想接受從其他窗口發(fā)送來(lái)的信息,必須對(duì)窗口對(duì)象的onmessage事件進(jìn)行監(jiān)聽(tīng),其他窗口可以通過(guò)postmessage方法來(lái)傳遞數(shù)據(jù),該方法使用兩個(gè)參數(shù):第一個(gè)參數(shù)為所發(fā)送的消息文本,但也可以是任何js對(duì)象,第二個(gè)參數(shù)為接收消息的對(duì)象窗口的url地址。
下面進(jìn)行試驗(yàn),主頁(yè)面index.html代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <script type="text/javascript"> function sendIt(){ document.getElementById("otherPage").contentWindow .postMessage(//向子窗口發(fā)出請(qǐng)求 document.getElementById("message").value,//值 "http://127.0.0.1:8020"http://目標(biāo)域 ) } </script> <body> <iframe src="http://127.0.0.1:8020/test2/JS/jstest/Cross-document-messaging/other.html" id="otherPage" width="" height=""></iframe> <br /><br /> <input type="text" name="message" id="message" value="" /> <input type="button" name="" id="" value="發(fā)送跨域消息" onclick="sendIt();" /> </body> </html>
窗口所引用頁(yè)面other.html代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> window.addEventListener("message",function(event){//通過(guò)onmessage監(jiān)聽(tīng) //將從父窗口傳來(lái)的數(shù)據(jù)展現(xiàn)出來(lái) document.getElementById("content").innerHTML+=event.data+"<br>"; },false); </script> </head> <body> 信息來(lái)自于另外一個(gè)域 <div id="content"> </div> </body> </html>
試驗(yàn)結(jié)果如下:
可以看到在81端口服務(wù)器中的index.html和8020端口的服務(wù)器中的other.html進(jìn)行的通信。
完整代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <script type="text/javascript"> function sendIt(){ document.getElementById("otherPage").contentWindow .postMessage(//向子窗口發(fā)出請(qǐng)求 document.getElementById("message").value,//值 "http://127.0.0.1:8020"http://目標(biāo)域 ) } </script> <body> <iframe src="http://127.0.0.1:8020/test2/JS/jstest/Cross-document-messaging/other.html" id="otherPage" width="" height=""></iframe> <br /><br /> <input type="text" name="message" id="message" value="" /> <input type="button" name="" id="" value="發(fā)送跨域消息" onclick="sendIt();" /> </body> </html>
CrossDocumentMessaging_index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript"> window.addEventListener("message",function(event){//通過(guò)onmessage監(jiān)聽(tīng) //將從父窗口傳來(lái)的數(shù)據(jù)展現(xiàn)出來(lái) document.getElementById("content").innerHTML+=event.data+"<br>"; },false); </script> </head> <body> 信息來(lái)自于另外一個(gè)域 <div id="content"> </div> </body> </html>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家了解熟悉常見(jiàn)的javascript跨域通信方法有所幫助。
- 跨域請(qǐng)求之jQuery的ajax jsonp的使用解惑
- jquery $.getJSON()跨域請(qǐng)求
- AJAX跨域請(qǐng)求json數(shù)據(jù)的實(shí)現(xiàn)方法
- jquery ajax jsonp跨域調(diào)用實(shí)例代碼
- jquery ajax跨域解決方法(json方式)
- jquery的ajax和getJson跨域獲取json數(shù)據(jù)的實(shí)現(xiàn)方法
- 用jQuery與JSONP輕松解決跨域訪問(wèn)的問(wèn)題
- getJSON跨域SyntaxError問(wèn)題分析
- js跨域問(wèn)題淺析及解決方法優(yōu)缺點(diǎn)對(duì)比
相關(guān)文章
通過(guò)javascript實(shí)現(xiàn)掃雷游戲代碼實(shí)例
這篇文章主要介紹了通過(guò)javascript實(shí)現(xiàn)掃雷游戲代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02獲取3個(gè)數(shù)組不重復(fù)的值的具體實(shí)現(xiàn)
先用concat拼接數(shù)組 ,再使用一個(gè)對(duì)象、一個(gè)新數(shù)組(用于存放不重復(fù)的數(shù)組)具體實(shí)現(xiàn)如下,感興趣的朋友可以參考2013-12-12JavaScript實(shí)現(xiàn)隱藏省略文字效果的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)隱藏省略文字效果的方法,涉及javascript基于事件響應(yīng)實(shí)現(xiàn)頁(yè)面字符串元素的獲取、截取、設(shè)置等相關(guān)操作技巧,需要的朋友可以參考下2017-04-04javascript關(guān)于open.window子頁(yè)面執(zhí)行完成后刷新父頁(yè)面的問(wèn)題分析
這篇文章主要介紹了javascript關(guān)于open.window子頁(yè)面執(zhí)行完成后刷新父頁(yè)面的問(wèn)題,實(shí)例分析了javascript操作子頁(yè)面的執(zhí)行與父頁(yè)面的刷新技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04javaScript事件學(xué)習(xí)小結(jié)(四)event的公共成員(屬性和方法)
這篇文章主要介紹了javaScript事件學(xué)習(xí)小結(jié)(四)event的公共成員(屬性和方法)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06改版了網(wǎng)上的一個(gè)js操作userdata
改版了網(wǎng)上的一個(gè)js操作userdata,并根據(jù)其它網(wǎng)友的文章結(jié)合了下。希望對(duì)需要的朋友有所幫助。2007-04-04JavaScript實(shí)現(xiàn)換膚效果(換背景)
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)換膚效果,即換背景功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09