JSONP解決跨域問題
- 1. 原理分析
-
- 1.1 同源政策
- 1.2 跨域的情形
- 1.3 跨域問題的解決方案
- 1.4 什麼是JSONP
- 2. JSONP方案具體實作
-
- 2.1動态建立script标簽
- 2.2 用jQuery中$.getJSON()實作JSONP
- 2.3 用jQuery中$.ajax()實作JSONP
- 2.4 總結:
最近在學習ajax跨域的問題,為了加深了解,寫篇部落格記錄一下。
1. 原理分析
1.1 同源政策
我們先來看看跨域問題涉及的一些概念:
- 源: 指頁面中資料的來源,由三部分指定:協定名、域名或IP位址、端口号
- 同源政策:不同源的用戶端js腳本在沒有明确授權的情況下,不能讀寫對方資源(a.com下的js腳本采用ajax不能讀取b.com裡面的檔案資料,會發生跨域錯誤)
- 跨域錯誤:(如下圖)
1.2 跨域的情形
上圖中有“紅色标記”的栗子都是不同源的情形。總的來說,協定名、域名、端口号任意一項不同就不同源。
1.3 跨域問題的解決方案
- 很多項目中,為了實作前後端分離,會特意将前端靜态資源(html/css/js等)與背景資料接口 分處在不同的伺服器上,是以域名/ip或端口号必然不相同,這就導緻了“跨域請求問題”。
-
跨域問題的解決方案有:
– 代理請求
–JSONP
–CORS
…
本文主要将jsonp方案解決跨域問題,其他方案學習透徹了再來總結。
1.4 什麼是JSONP
- JSONP(json with padding)是json的一種使用模式。
-
通過上面的學習,我們已經知道,由于同源政策浏覽器會禁止JS跨域。
但是,我們知道script标簽是允許跨域請求的。利用這個特性,用戶端使用script代替XHR( XMLHttpRequest)發起跨域請求,伺服器在json響應資料前後填充一些額外的内容,就稱為“填充式JSON”——JSONP
2. JSONP方案具體實作
JSONP實作跨域請求的原理就是動态建立script标簽,利用“src”不受同源政策限制的性質來實作跨域擷取資料。
菜鳥教程提供了一個連結,我們可以用它練練手~
連結:https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction
2.1動态建立script标簽
下面栗子很簡單,就不細說了~
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 執行個體</title>
</head>
<body>
<script>
function callbackFunction(data){
console.log("i got it");
console.log(data);
}
</script>
<script>
window.onload=function(){
var script=document.createElement("script");
script.src="https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction";
document.head.append(script);
}
</script>
</body>
</html>
2.2 用jQuery中$.getJSON()實作JSONP
- $.getJSON()方法允許通過使用JSONP形式的回調函數來加載其他網域的JSON資料
- 使用$.getJSON()方法實作跨域請求,需要在請求路徑URL後增加callback=?, jQuery将自動替換“?”為正确的函數名,以執行回調函數。
注:下面代碼中路徑後是jsoncallback=?,因為服務端的代碼中回調函數名為jsoncallback,前後端應該是一緻的
記得引入jQuery檔案!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 執行個體</title>
<script src="https://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script>
</head>
<body>
<script>
$.getJSON("https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=?",function(data){console.log(data);})
</script>
</body>
</html>
2.3 用jQuery中$.ajax()實作JSONP
$.ajax()方法同樣可以實作JSONP跨域請求,我們主要來看看它的一些選項參數:
- url:請求位址
- type:請求方式
- dataType:“jsonp” 必寫,設定伺服器端傳回的資料類型,這裡是"jsonp"
- jsonp:獲得jsonp回調函數名的參數名,這個值用于代替"callback=?"(本例就是用"jsoncallback=?“代替了"callback=?”),一般預設都是callback
- jsonCallback:可選,為JSONP請求指定一個回調函數名,這個值将代替jQuery自動生成的随機函數名(就是代替"callback=?"中的問号)
- success:請求成功後的回調函數。
知道這些選項參數的意思了,我們再看看上面給到的那個連結:
https://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction
我們看到調用的url中,jsoncallback參數告訴伺服器,我的本地回調函數叫做callbackFunction,讓伺服器請把查詢結果傳入這個函數中。伺服器傳遞給callbackFunction函數json格式的資料:callbackFunction([“customername1”,“customername2”])
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 執行個體</title>
<script src="https://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script>
</head>
<body>
<script>
$.ajax({
url: "https://www.runoob.com/try/ajax/jsonp.php",
type: "get",
dataType: "jsonp",
jsonp: "jsoncallback",
success: function(data){
console.log(data);
}
})
</script>
</body>
</html>
2.4 總結:
- ajax和jsonp本質上是不同的東西。ajax的核心是通過XmlHttpRequest擷取非本頁内容,而jsonp的核心則是動态添加script标簽來調用伺服器提供的js腳本。
- JSONP方案屬于用戶端直接請求,不存在二次請求的問題;但是,不足是script标簽隻能發起get請求。