前言
前幾天调鲸,有個(gè)朋友問(wèn)我跨域的問(wèn)題,尋思著找篇文章給他理解挽荡。找了半天都沒(méi)有直中要害藐石,個(gè)人認(rèn)為都是理解的模棱兩可,所以花時(shí)間把自己的對(duì)ajax跨域的理解寫下來(lái)定拟。
什么是跨域于微?
假設(shè)我訪問(wèn)a 站點(diǎn)逗嫡,在a站點(diǎn)得到一個(gè)頁(yè)面,在a 站點(diǎn)的這個(gè)頁(yè)面想去訪問(wèn)b 站點(diǎn)的資源株依,這個(gè)是就會(huì)產(chǎn)生一個(gè)跨域的效果驱证。由于瀏覽器是有安全限制的,所以a 站點(diǎn)無(wú)法訪問(wèn)到b站點(diǎn)的資源恋腕。
比如我現(xiàn)在訪問(wèn) www.1.com 獲取到一個(gè)頁(yè)面.通過(guò)這個(gè)頁(yè)面去訪問(wèn)www.2.com獲取資源抹锄。就會(huì)產(chǎn)生跨域。
問(wèn)題展現(xiàn)
接口我用的是聚合數(shù)據(jù)荠藤,有接口調(diào)用次數(shù)限制伙单,如若接口調(diào)用有問(wèn)題,請(qǐng)自行申請(qǐng)接口哈肖。
1吻育、創(chuàng)建一個(gè)ajaxDemo_1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajax</title>
</head>
<body>
這是一個(gè)有跨域問(wèn)題的頁(yè)面
<script src="./jquery.min.js"></script>
<script type="text/javascript">
$.ajax({
type: "get",
cache: false,
url: 'http://apis.juhe.cn/oil/region?key=1b9411b68adda384780872fabcafc16d&city=%e5%8c%97%e4%ba%ac',
dataType: "json",
success: function(result) {
console.log(JSON.stringify(result));
},
error: function(err) {
console.log('err10: ');
console.log(err);
}
});
</script>
</body>
</html>
2、將ajaxDemo_1.html放到本地node.js服務(wù)器上運(yùn)行
如何解決淤井?
1布疼、jsonp(只能解決get請(qǐng)求跨域問(wèn)題)
創(chuàng)建一個(gè)ajaxDemo_2.html 發(fā)起get請(qǐng)求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajaxDemo_2</title>
</head>
<body>
這是一個(gè)用jsonp解決get請(qǐng)求跨域問(wèn)題的頁(yè)面
<script src="./jquery.min.js"></script>
<script type="text/javascript">
$.ajax({
type: "get",
cache: false,
url: 'http://apis.juhe.cn/oil/region?key=1b9411b68adda384780872fabcafc16d&city=%e8%a1%a1%e9%98%b3',
dataType: "jsonp",
success: function(result) {
console.log(JSON.stringify(result));
},
error: function(err) {
console.log('err10: ');
console.log(err);
}
});
</script>
</body>
</html>
ajax使用script元素發(fā)送jsonp請(qǐng)求
使用<script>元素進(jìn)行ajax傳輸?shù)脑颍?br>
1币狠、它不受同源策略的影響游两,因此可以使用它們從其他服務(wù)器請(qǐng)求數(shù)據(jù)。
2总寻、包含JSON編碼數(shù)據(jù)的響應(yīng)體會(huì)自動(dòng)解碼(即執(zhí)行)器罐。
結(jié)論:當(dāng)通過(guò)<script>元素調(diào)用數(shù)據(jù)時(shí)梢为,響應(yīng)內(nèi)容必須用js函數(shù)名和圓括號(hào)包裹起來(lái)渐行,而不是發(fā)送一段json數(shù)據(jù)。而且通過(guò)<script>元素只能加載get請(qǐng)求而不能加載post請(qǐng)求
2铸董、cors(跨域資源共享 Cross-Origin Resource Sharing)
通過(guò)cors使跨域問(wèn)題在get請(qǐng)求和post請(qǐng)求都可以解決
2.1祟印、cors原理
CORS定義一種跨域訪問(wèn)的機(jī)制,可以讓AJAX實(shí)現(xiàn)跨域訪問(wèn)粟害。CORS 允許一個(gè)域上的網(wǎng)絡(luò)應(yīng)用向另一個(gè)域提交跨域 AJAX 請(qǐng)求蕴忆。實(shí)現(xiàn)此功能非常簡(jiǎn)單,只需由服務(wù)器發(fā)送一個(gè)響應(yīng)標(biāo)頭即可
2.2CORS瀏覽器支持情況
喜聞樂(lè)見悲幅、普大喜奔的支持情況套鹅,尤其是在移動(dòng)終端上,除了opera Mini汰具;
PC上的現(xiàn)代瀏覽器都能友好的支持卓鹿,除了IE9-,不過(guò)前端工程師對(duì)這種情況早應(yīng)該習(xí)慣了...
2.3 應(yīng)用
假設(shè)我們頁(yè)面或者應(yīng)用已在 http://www.test1.com 上了留荔,而我們打算從 http://www.test2.com 請(qǐng)求提取數(shù)據(jù)吟孙。一般情況下,如果我們直接使用 AJAX 來(lái)請(qǐng)求將會(huì)失敗,瀏覽器也會(huì)返回“源不匹配”的錯(cuò)誤杰妓,"跨域"也就以此由來(lái)藻治。
利用 CORS,http://www.test2.com 只需添加一個(gè)標(biāo)頭巷挥,就可以允許來(lái)自 http://www.test1.com 的請(qǐng)求桩卵,下圖是我在服務(wù)器返回中的 header() 設(shè)置,“*”號(hào)表示允許任何域向我們的服務(wù)端提交請(qǐng)求:
也可以設(shè)置指定的域名倍宾,如域名 http://www.test2.com 吸占,那么就允許來(lái)自這個(gè)域名的請(qǐng)求:
當(dāng)前我設(shè)置的header為“*”,任意一個(gè)請(qǐng)求過(guò)來(lái)之后服務(wù)端我們都可以進(jìn)行處理&響應(yīng)凿宾,那么在調(diào)試工具中可以看到其頭信息設(shè)置矾屯,其中見紅框中有一項(xiàng)信息是“Access-Control-Allow-Origin:* ”,表示我們已經(jīng)啟用CORS初厚。
示例代碼
https://github.com/yangxiaopingios/AjaxDemo