瀏覽器與伺服器通訊技術——jsonp

snsart發表於2019-05-23

除了使用cros實現跨域資源訪問之外,另一種實現跨域資源訪問的技術是藉助DOM中能夠執行跨域請求的功能,在不依賴XHR物件的情況下傳送某種請求。比如藉助<img>,<script>標籤的src屬性。其中最流行的是JSONP技術。

一、跨域載入指令碼

先看下面一段程式碼:

1 function handleResponse(response){
2     alert("name:"+response.name+","+"age:"+response.age);
3 }
4 
5 jsonData={
6     name:"xiaoming",
7     age:20
8 }
9 handleResponse(jsonData);

上例中,handleResponse方法顯然是可以訪問jsonData中的資料的。如果我們把上例中5-9行的指令碼放在另一臺伺服器上,命名為json.js,通過script的src屬性載入這段指令碼。最終的效果和上例是等效的,如下例:

1 function handleResponse(response){
2     alert("name:"+response.name+","+"age:"+response.age);
3 }
4 //跨域載入json.js指令碼    
5 var script=document.createElement("script");
6 script.src="http://www.somewhere.com/json.js";
7 document.body.insertBefore(script,document.body.firstChild);

放在其他伺服器上的json.js指令碼

1 jsonData={
2     name:"xiaoming",
3     age:20
4 }
5 handleResponse(jsonData);

這樣就實現了跨域資源的訪問;

二、什麼是JSONP

通過script的src屬性載入的指令碼資料稱為JSONP。通過分析上例中的json.js指令碼,我們可以發現JSONP有兩部分組成:1.json資料,比如上例的jsonData,2.回撥函式,比如上例的handleResponse。也可以把JSONP理解為包含在回撥函式中的json,比如:

handleResponse({
    name:"xiaoming",
    age:20
});

三、傳送回撥函式名

通過上例可知客戶端定義的回撥函式名稱和伺服器端jsonp中的回撥函式名稱必須保持一致。為了增加靈活性,即客戶端可以任意定義回撥函式名,我們需要請求服務時把回撥函式名作為url上的查詢字串傳送給伺服器,伺服器拿到函式名後,再生成jsonp傳送回客戶端。客戶端程式碼和服務端程式碼如下:

客戶端

1 function handleResponse(response){
2     alert("name:"+response.name+","+"age:"+response.age);
3 }
4 
5 var script=document.createElement("script");
6 script.src="http://www.test.com/test/test.php?jsoncallback=handleResponse";//函式名作為查詢字串發給伺服器
7 document.body.insertBefore(script,document.body.firstChild);    

伺服器端php程式碼

 1 <?php
 2 
 3 header('Content-type: application/json');
 4 //獲取回撥函式名
 5 $jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
 6 //json資料
 7 $json_data = '{
 8     "name":"xiaoming",
 9     "age":29
10 }';
11 //輸出jsonp格式的資料
12 echo $jsoncallback . "(" . $json_data . ")";
13 
14 ?>

四、jsonp的優缺點

通過jsonp可以直接跨域訪問響應文字,支援瀏覽器和伺服器之間雙向通訊,並且不需要定義伺服器上的響應標頭檔案。使用jsonp的主要缺點是安全問題,由於jsonp是從其他域載入程式碼並執行,如果其它域不安全,很可能會在響應中夾帶一些惡意程式碼。因此在使用不是自己維護的服務時,一定要保證它安全可靠。

相關文章