jsonp跨域請求,常見的集中書寫方式,及優缺點比較
符合Web2.0特徵的眾多網站一個明顯的特點就是採用Ajax。Ajax提供了在後臺提交請求訪問資料的功能。其實現主要使用的是XMLHttpRequest函式,這個函式允許客戶端的Javascript傳送到伺服器端的HTTP請求並獲得返回資料。Ajax同時也是目前眾多的Mashup背後的驅動力量,他們都利用Ajax來聚合不同來源的資訊。
理解同源策略的限制
同源策略是指阻止程式碼獲得或者更改從另一個域名下獲得的檔案或者資訊。也就是說我們的請求地址必須和當前網站的地指相同。同源策略通過隔離來實現對資源的保護。這個策略的歷史非常悠久
所謂同源是指,域名,協議,埠均相同,不明白沒關係,舉個例子:
http://www.123.com/index.html 呼叫 http://www.123.com/server.PHP (非跨域)
http://www.123.com/index.html 呼叫 http://www.456.com/server.
http://abc.123.com/index.html 呼叫 http://def.123.com/server.php (子域名不同:abc/def,跨域)
http://www.123.com:8080/index.html 呼叫 http://www.123.com:8081/server.php (埠不同:8080/8081,跨域)
http://www.123.com/index.html 呼叫 https://www.123.com/server.php (協議不同:http/https,跨域)
請注意:localhost和127.0.0.1雖然都指向本機,但也屬於跨域。
瀏覽器執行JavaScript指令碼時,會檢查這個指令碼屬於哪個頁面,如果不是同源頁面,就不會被執行。
解決方法:
1.jsonp
優點:1.1它不像XMLHttpRequest物件實現的Ajax請求那樣受到同源策略的限制,JSONP可以跨越同源策略;
1.2它的相容性更好,在更加古老的瀏覽器中都可以執行,不需要XMLHttpRequest或ActiveX的支援
1.3在請求完畢後可以通過呼叫callback的方式回傳結果。將回調方法的許可權給了呼叫方。這個就相當於將controller層和view層終於分開了。我提供的jsonp服務只提供純服務的資料,至於提供服務以 後的頁面渲染和後續view操作都由呼叫者來自己定義就好了。如果有兩個頁面需要渲染同一份資料,你們只需要有不同的渲染邏輯就可以了,邏輯都可以使用同 一個jsonp服務。
缺點:2.1它只支援GET請求而不支援POST等其它型別的HTTP請求
2.2它只支援跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript呼叫的問題。
2.3 jsonp在呼叫失敗的時候不會返回各種HTTP狀態碼。
2.4缺點是安全性。萬一假如提供jsonp的服務存在頁面注入漏洞,即它返回的javascript的內容被人控制的。那麼結果是什麼?所有呼叫這個 jsonp的網站都會存在漏洞。於是無法把危險控制在一個域名下…所以在使用jsonp的時候必須要保證使用的jsonp服務必須是安全可信的。
示例程式碼:
後臺程式碼(php):http://localhost/json.php
<?php
header("Content-type:text/json");
$json2='{"success":true,"array":[{"top1_id":11,"top1":"思想品德修養","top2_id":2,"top2":"公民素養"},{"top1_id":11,"top1":"思想品德修養"}]}';
echo $_GET["call"].'('.$json2.')';
?>
前臺頁面(普通html頁面):
方法1:直接請求檔案地址,從回撥函式獲取資料
<script type="text/javascript">
function callBackOne(data){
console.log(data);
}
</script>
<script src="http://localhost/json.php?call=callBackOne" type="text/javascript"></script>
方法2:
動態拼接script標籤進行請求
<script type="text/javascript">
function callBackTwo(data){
console.log(data);
}
var urlSrc = 'http://localhost/json.php?call=callBackTwo';
var script = document.createElement('script');
script.setAttribute('src',urlSrc);
document.getElementsByTagName('head')[0].appendChild(script);
</script>
方法3:通過jQuery的內建方法呼叫
<script type="text/javascript">
function callBackThree(data){
console.log(data);
}
$.getJSON('http://localhost/json.php?call=?',function(data){
console.log(data);
});
</script>
方法4:ajax形式
<script type="text/javascript">
$.ajax({
url:'http://localhost/json.php',
type:'POST',
dataType:'jsonp',
jsonp:'call',
jsonpCallback:'callBackFour',
success:function(data){
console.log("success返回值",data);
},
error:function(errorMsg){
console.log(errorMsg);
}
});
function callBackFour(data){
console.log(data);
}
</script>
以上的4種方法是基本上大家用的最多的方法,當然如果可行的方法是將php檔案直接寫成介面的形式,當請求時新增訪問的引數,直接獲取相應的資料
2.代理
例如www.123.com/index.html需要呼叫www.456.com/server.php,可以寫一個介面www.123.com/server.php,由這個介面在後端去呼叫 www.456.com/server.php並拿到返回值,然後再返回給index.html,這就是一個代理的模式。相當於繞過了瀏覽器端,自然就不存在跨域問題。
3、PHP端修改header(XHR2方式)
在php介面指令碼中加入以下兩句即可:
header('Access-Control-Allow-Origin:*');//允許所有來源訪問
header('Access-Control-Allow-Method:POST,GET');//允許訪問的方式