常見的javascript跨域通訊方法_javascript技巧

來源:互聯網
上載者:User

本文主要介紹幾種常見的javascript跨域通訊方法。首先講解一下JSONP。
1、JSONP
JSONP(JSON with Padding)是JSON的一種“使用模式”,可用於解決主流瀏覽器的跨域資料訪問的問題。由於同源策略,一般來說位於 server1.example.com 的網頁無法與不是 server1.example.com的伺服器溝通,而 HTML 的<script> 元素是一個例外。利用 <script> 元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON 資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料並不是JSON,而是任意的JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。
下面我們來介紹下JSONP的具體實現。
我們知道,哪怕跨域js檔案中的代碼(當然指符合web指令碼安全性原則的),web頁面也是可以無條件執行的。遠程伺服器remoteserver.com根目錄下有個remote.js檔案代碼如下:
alert('我是遠程檔案'); 
本機伺服器localserver.com下有個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" src="http://remoteserver.com/remote.js"></script> </head> <body>  </body> </html>

毫無疑問,頁面將會彈出一個提示表單,顯示跨域調用成功。

現在我們在jsonp.html頁面定義一個函數,然後在遠程remote.js中傳入資料進行調用。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">  var localHandler = function(data){   alert('我是本地函數,可以被跨域的remote.js檔案調用,遠程js帶來的資料是:' + data.result);  };  </script>  <script type="text/javascript" src="http://remoteserver.com/remote.js"></script> </head> <body>  </body> </html> 

remote.js檔案代碼如下:
localHandler({"result":"我是遠程js帶來的資料"}); 
成功運行,看來跨域遠程擷取資料的目的實現了,但是又一個問題出現了,我怎麼讓遠程js知道它應該調用的本地函數叫什麼名字呢?這時我們就需要將服務端提供的js指令碼動態產生就行了,調用者可用通過傳參告訴服務端自己需要什麼函數,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">  // 得到航班資訊查詢結果後的回呼函數  var flightHandler = function(data){   alert('你查詢的航班結果是:票價 ' + data.price + ' 元,' + '餘票 ' + data.tickets + ' 張。');  };  // 提供jsonp服務的url地址(不管是什麼類型的地址,最終產生的傳回值都是一段javascript代碼)  var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";  // 建立script標籤,設定其屬性  var script = document.createElement('script');  script.setAttribute('src', url);  // 把script標籤加入head,此時調用開始  document.getElementsByTagName('head')[0].appendChild(script);  </script> </head> <body>  </body> </html> 

這次的代碼變化比較大,不再直接把遠程js檔案寫死,而是編碼實現動態查詢,而這也正是jsonp用戶端實現的核心部分,本例中的重點也就在於如何完成jsonp調用的全過程。
我們看到調用的url中傳遞了一個code參數,告訴伺服器我要查的是CA1998次航班的資訊,而callback參數則告訴伺服器,我的本地回呼函數叫做flightHandler,所以請把查詢結果傳入這個函數中進行調用。這個叫做flightResult.aspx的頁面產生了一段這樣的代碼提供給jsonp.html(服務端的實現這裡就不示範了,與你選用的語言無關,說到底就是拼接字串):

flightHandler({  "code": "CA1998",  "price": 1780,  "tickets": 5 }); 

傳遞給flightHandler函數的是一個json,它描述了航班的基本資料。運行一下頁面,成功彈出提示視窗,jsonp的執行全過程順利完成!
但是JSONP存在一點問題,就是由遠程服務端負責封裝json資料,並調用命名函數,這種方式存在安全隱患,在使用JSONP時,必須完全信任服務端所提供的資料,惡意指令碼就可以直接接管我們的應用。所以接下來我們要介紹一種別的方式,來避免這種安全隱患。
2、CORS
CORS(Cross OriginResource Sharing,跨源資源共用)實現了跨源XMLHttpRequests,跨源HTTP請求包括一個Origin頭部,它為伺服器提供HTTP請求的源資訊。頭部由瀏覽器保護,不能被應用程式代碼更改。這種方式遠比評估外部輸入的方式安全。
以前的ajax只能同源請求,現在通過XMLHttpRequests二級,可以進行跨域請求。假設我們頁面或者應用已在 http://www.test1.com 上了,而我們打算從 http://www.test2.com 請求提取資料。一般情況下,如果我們直接使用 AJAX 來請求將會失敗,瀏覽器也會返回“源不匹配”的錯誤,"跨域"也就以此由來。
利用 CORS,http://www.test2.com 只需添加一個標題,就可以允許來自 http://www.test1.com 的請求。php代碼如下:

header("Access-Comtrol-Allow-Origin:*");<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span> 

其中*表示允許任何域向我們的服務端提交請求。也可以設定指定的網域名稱,代碼如下:

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

設定好頭資訊之後,其他域就可以進行請求了。
        使用"跨域資源共用"的前提,是瀏覽器必須支援這個功能,而且伺服器端必須同意這種"跨域"。如果能夠滿足上面的條件,則代碼的寫法與不跨域的請求完全一樣。
xhr.open('GET', ' http://www.test2.com '); 
 接下來介紹另外一種即時通訊方式:
3、Cross-document messaging
跨文檔資訊通訊。使用這個功能,只要擷取到網頁所在視窗對象的執行個體,不僅同原的web網頁可以互相通訊,也可以實現跨域通訊。要想接受從其他視窗發送來的資訊,必須對視窗對象的onmessage事件進行監聽,其他視窗可以通過postmessage方法來傳遞資料,該方法使用兩個參數:第一個參數為所發送的訊息文本,但也可以是任何js對象,第二個參數為接收訊息的對象視窗的url地址。
下面進行實驗,首頁面index.html代碼如下:

<!DOCTYPE html> <html>  <head>   <meta charset="utf-8">   <title></title>  </head> <script type="text/javascript">  function sendIt(){   document.getElementById("otherPage").contentWindow   .postMessage(//向子視窗發出請求    document.getElementById("message").value,//值    "http://127.0.0.1:8020"//目標域   )  } </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="發送跨域訊息" onclick="sendIt();" />  </body> </html> 

 視窗所引用頁面other.html代碼如下:

<!DOCTYPE html> <html>  <head>   <meta charset="utf-8">   <title></title> <script type="text/javascript">  window.addEventListener("message",function(event){//通過onmessage監聽   //將從父視窗傳來的資料展現出來   document.getElementById("content").innerHTML+=event.data+"<br>";  },false); </script>  </head>  <body>   資訊來自於另外一個域   <div id="content">       </div>  </body> </html>

實驗結果如下:


可以看到在81連接埠伺服器中的index.html和8020連接埠的伺服器中的other.html進行的通訊。
完整代碼如下:

<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title></title> </head><script type="text/javascript"> function sendIt(){ document.getElementById("otherPage").contentWindow .postMessage(//向子視窗發出請求 document.getElementById("message").value,//值 "http://127.0.0.1:8020"//目標域 ) }</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="發送跨域訊息" 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){//通過onmessage監聽 //將從父視窗傳來的資料展現出來 document.getElementById("content").innerHTML+=event.data+"<br>"; },false);</script> </head> <body> 資訊來自於另外一個域 <div id="content">  </div> </body></html>

以上就是本文的全部內容,希望對大家瞭解熟悉常見的javascript跨域通訊方法有所協助。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.