JSONP跨域請求原理及示例
Jsonp的跨域問題,再講之前先說明一下什麼是同源策略。
來自百度的介紹
同源策略,它是由Netscape提出的一個著名的安全策略。現在所有支援JavaScript 的瀏覽器都會使用這個策略。所謂同源是指,域名,協議,埠相同。當一個瀏覽器的兩個tab頁中分別開啟來 百度和谷歌的頁面。當瀏覽器的百度tab頁執行一個指令碼的時候會檢查這個指令碼是屬於哪個頁面的,即檢查是否同源,只有和百度同源的指令碼才會被執行。如果非同源,那麼在請求資料時,瀏覽器會在控制檯中報一個異常,提示拒絕訪問。
如下:下表引自網路其他部落格大牛
JSON和JSONP
Json 和jsonp看起來好像啊,那麼他們之間有什麼聯絡嗎?
JSON(JavaScript Object Notation)是一種輕量級的資料交換格式,其具體格式及用法,我的這篇文章有介紹
JSONP 是JSON with Padding的簡稱,它是一個非官方的協議,它允許在伺服器端整合Script tags返回客戶端,通過javascript callback的形式實現跨域訪問。(這是百度的說法,不懂沒關係,我細細講解)
html頁面
<div id="bdlog">
<img src="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png">
</div >
結果展示:
看到了吧,<img>
中的src屬性既可以請求本地圖片,也可以請求網上資源。也就是說html中的src屬性是支援跨域的。同理jsonp跨域請求也是利用src屬性,只不過用的是<script></script>
標籤。
來看個jsonp的小例子
jsonp.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonp請求資源</title >
</head>
<body>
</body>
</html>
<script type="text/javascript" src="js/data.js
data.js
console.log("我被jsonp請求了!");
開啟控制檯,看一下:
看,jsonp實現了本地資料的請求。如果我想請求伺服器的資料該是怎樣去實現呢?
JSONP的原理解析
jsonp.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonp請求伺服器資料</title>
</head>
<body>
</body>
</html>
<script type="text/javascript" src="http://127.0.0.1/2017_06_26/jsonp/02jsonp.php"></script>
jsonp.php
<?php
echo "成功請求伺服器!";
?>
結果如下:
我們會發現頁面請求了 jsonp.php頁面,並且使用的是get方法。也就是說jsonp請求資料預設使用的是get方法。剛才我們再介紹jsonp的時候,說了一下 允許在伺服器端整合Script tags返回客戶端,通過javascript callback的形式實現跨域訪問。
那麼我們繼續改進html頁面,在請求的url中新增一個?callback=test引數.其中test是寫在html中的js函式
jsonp.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonp請求伺服器資料</title>
</head>
<body>
</body>
</html>
<script>
function test(data) {
console.log("測試能否呼叫我這個test()函式");
console.log(data);
}
</script>
<script type="text/javascript" src="http://127.0.0.1/2017_06_26/jsonp/jsonp.php?callback=test"></script>
jsonp.php
<?php
// 獲取到了 test.()
返回的是 test({"name":"jsonp","color":"green"});
echo $_GET['callback'].'({"name":"jsonp","color":"green"})';
?>
結果是:
通過script標籤引入一個js檔案,這個js檔案載入成功後會執行我們在url拼接一個callback引數,通過get方式請求伺服器,伺服器返回的資料若是json字串將自動轉化為js物件。所以jsonp是需要伺服器端和客戶端相互配合的。
看圖也許會明瞭一些:
但是每次寫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery傳送jsonp請求</title>
</head>
<body>
<input type="button" value="jQuery傳送jsonp請求" id="jq_jsonp">
</body>
</html>
<!--匯入jQuery-->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script>
$(function () {
$('#jq_jsonp').click(function () {
$.ajax({
url:'jQ_jsonp.php',
success:function (data) {
console.log(data);
},
dataType:'jsonp'
})
})
})
</script>
可以發現,我們並沒有寫callback方法,jQuery自動幫我們封裝了一個callback方法。
如果想要設定 自己的 回撥函式 可以通過jsonpCallback 來設定 自己的名字
<script>
function myJSONPCallback(data) {
console.log("自己寫的callback函式"+data);
}
$(function () {
$('#jq_jsonp').click(function () {
$.ajax({
url:'jQ_jsonp.php',
success:function (data) {
console.log(data);
},
dataType:'jsonp',
jsonpCallback:"myJSONPCallback"
})
})
})
</script>
jQ_jsonp.php
<?php
echo $_GET['callback'].'("哈哈哈")';
?>
總結:JSONP(JSON with Padding)其本質是利用了<script src=""></script>
標籤具有可跨域的特性,由服務端返回一個預先定義好的Javascript函式的呼叫,並且將伺服器資料以該函式引數的形式傳遞過來,此方法需要前後端配合完成。**
只能以GET方式請求.**