什么是跨域
- 請(qǐng)求協(xié)議(
http,https
)不同 - 域名(
domain
)不同 - 端口(
port
)不同
更詳細(xì)的說(shuō)明可以看下表:
URL | 說(shuō)明 | 是否允許通信 |
---|---|---|
http://www.a.com/a.js http://www.a.com/b.js | 同一域名下 | 允許 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js | 同一域名下不同文件夾 | 允許 |
http://www.a.com:8000/a.js http://www.a.com/b.js | 同一域名,不同端口 | 不允許 |
http://www.a.com/a.js https://www.a.com/b.js | 同一域名,不同協(xié)議 | 不允許 |
http://www.a.com/a.js http://70.32.92.74/b.js | 域名和域名對(duì)應(yīng)ip | 不允許 |
http://www.a.com/a.js http://script.a.com/b.js | 主域相同睬涧,子域不同 | 不允許 |
http://www.a.com/a.js http://a.com/b.js | 同一域名碘赖,不同二級(jí)域名(同上) | 不允許(cookie這種情況下也不允許訪(fǎng)問(wèn)) |
http://www.cnblogs.com/a.js http://www.a.com/b.js | 不同域名 | 不允許 |
跨域解決方案之 JSONP
Jsonp (JSON with Padding) 是 json 的一種"使用模式"诺祸,可以讓網(wǎng)頁(yè)從別的域名(網(wǎng)站)那獲取資料晒杈,即跨域讀取數(shù)據(jù)论悴。
由于跨域的存在计贰,使資源交互在不同域名間變的復(fù)雜和安全钦睡。對(duì)于跨域數(shù)據(jù)傳輸,當(dāng)數(shù)據(jù)長(zhǎng)度較小(get的長(zhǎng)度內(nèi))躁倒,jsonp是一種較好的解決方案荞怒。
為什么我們從不同的域(網(wǎng)站)訪(fǎng)問(wèn)數(shù)據(jù)需要一個(gè)特殊的技術(shù)(JSONP )呢洒琢?這是因?yàn)?strong>瀏覽器同源策略,它是由Netscape提出的一個(gè)著名的安全策略褐桌,現(xiàn)在所有支持JavaScript 的瀏覽器都會(huì)使用這個(gè)策略
衰抑。
Jsonp的原理是利用 <script>
元素的開(kāi)放策略,網(wǎng)頁(yè)可以得到從其他來(lái)源動(dòng)態(tài)獲取的 JSON 數(shù)據(jù)荧嵌,數(shù)據(jù)被包裹在一個(gè)JavaScript 函數(shù)中呛踊。
jsonp的js端調(diào)用
主要功能:通過(guò)jsonp向服務(wù)器,調(diào)用相應(yīng)接口啦撮,獲應(yīng)數(shù)據(jù)谭网;根據(jù)獲取數(shù)據(jù)結(jié)果做出相應(yīng)回調(diào)。
<script type="text/javascript">
$(function () {
alert("start...");
$.ajax({
type: "get",
// 這個(gè)就是不同于當(dāng)前域的一個(gè)URL地址
url: "http://your_site_url",
dataType: "jsonp",
//傳遞給請(qǐng)求處理程序或頁(yè)面的赃春,用以獲得jsonp回調(diào)函數(shù)名的參數(shù)名(默認(rèn)為:callback)
jsonp: "callback",
//自定義的jsonp回調(diào)函數(shù)名稱(chēng)愉择,默認(rèn)為jQuery自動(dòng)生成的隨機(jī)函數(shù)名
// jsonpcallback與上面的jsonp值一致
jsonpCallback:"success_jsonpCallback",
data: "name=admin",
success : function(json){//返回的json數(shù)據(jù)
console.log(josn.message);//回調(diào)輸出
alert('success');
},
error:function(){
alert('fail');
}
});
alert("end...");
});
</script>
jsonp 服務(wù)器端 (php)
<?php
$data = ".......";
$callback = $_GET['callback'];
echo $callback.'('.json_encode($data).')';
exit;
?>
Jsonp使用注意事項(xiàng)
1.安全問(wèn)題
JSONP
可能會(huì)引起 CSRF(Cross-site request forgery 跨站請(qǐng)求偽造)
攻擊或 XSS (Cross Site Scripting 跨站腳本攻擊)
漏洞。
對(duì)于支持 JSONP
的接口织中,寫(xiě)接口時(shí)數(shù)據(jù)可能會(huì)被篡改锥涕,讀接口時(shí)數(shù)據(jù)可能會(huì)被劫持。
XSS示例:
輸出 JSON 時(shí)狭吼,沒(méi)有嚴(yán)格定義好
Content-Type(Content-Type: application/json)
直接導(dǎo)致了一個(gè)典型的 XSS 漏洞:http://127.0.0.1/getUsers.php?callback=<script>alert(/xss/)</script>
2.傳值問(wèn)題
使用Jsonp進(jìn)行跨域請(qǐng)求层坠,只能通過(guò)GET請(qǐng)求傳值!5篌稀窿春!
可以從Josnp的原理來(lái)理解:
JSONP
的最基本的原理是動(dòng)態(tài)添加一個(gè)<script>
標(biāo)簽,而script
標(biāo)簽的src
屬性是沒(méi)有跨域的限制的采盒。這樣說(shuō)來(lái),這種跨域方式其實(shí)與ajax XmlHttpRequest
協(xié)議無(wú)關(guān)了蔚润。
可以說(shuō)jsonp
的方式原理上和<script src="http://跨域/...xx.js"></script>
是一致的磅氨,因?yàn)樗脑韺?shí)際上就是 使用js
的script
標(biāo)簽 進(jìn)行傳參,那么必然是get
方式的了嫡纠,和瀏覽器中敲入一個(gè)url
一樣烦租。
預(yù)先定義callback函數(shù)
function myfunc(data) {
console.log(data)
}
dom中插入script標(biāo)簽
<!-- callback參數(shù)對(duì)象對(duì)應(yīng)上面callback函數(shù)名 -->
<script src="http://example.com/jsonp.js?callback=myfunc"></script>
瀏覽器請(qǐng)求//example.com/jsonp.js?callback=myfunc, 得到內(nèi)容
myfunc({"foo": "bar"}) //數(shù)據(jù)傳入到了callback函數(shù)
本質(zhì)上是通過(guò)script標(biāo)簽獲取數(shù)據(jù), script標(biāo)簽是只支持GET的。
總結(jié)
- 目前來(lái)說(shuō)除盏,數(shù)據(jù)量小的跨域傳輸叉橱,jsonp是一種很好的解決方案。
-
jsonp
在data中可以自動(dòng)識(shí)別者蠕,res.status窃祝,res.info
等狀態(tài)位,比較方便踱侣。 - php 端的接受代碼最好不要采用
Access-Control-Allow-Origin:*
風(fēng)險(xiǎn)太大粪小。 -
Jsonp
的兼容性更好大磺,在更加古老的瀏覽器中都 可以運(yùn)行。 -
Jsonp
只支持GET請(qǐng)求而不支持POST等其它類(lèi)型的HTTP請(qǐng)求 -
Jsonp
只支持跨域HTTP請(qǐng)求這種情況探膊,不能解決不同域的兩個(gè)頁(yè)面之間如何進(jìn)行JavaScript調(diào)用的問(wèn)題杠愧。