前言
前幾天,有個朋友問我跨域的問題,尋思著找篇文章給他理解。找了半天都沒有直中要害,個人認為都是理解的模棱兩可,所以花時間把自己的對ajax跨域的理解寫下來。
什么是跨域?
假設我訪問a 站點,在a站點得到一個頁面,在a 站點的這個頁面想去訪問b 站點的資源,這個是就會產生一個跨域的效果。由于瀏覽器是有安全限制的,所以a 站點無法訪問到b站點的資源。
比如我現在訪問 www.1.com 獲取到一個頁面.通過這個頁面去訪問www.2.com獲取資源。就會產生跨域。
問題展現
接口我用的是聚合數據,有接口調用次數限制,如若接口調用有問題,請自行申請接口。
1、創建一個ajaxDemo_1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajax</title>
</head>
<body>
這是一個有跨域問題的頁面
<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服務器上運行
如何解決?
1、jsonp(只能解決get請求跨域問題)
創建一個ajaxDemo_2.html 發起get請求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajaxDemo_2</title>
</head>
<body>
這是一個用jsonp解決get請求跨域問題的頁面
<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元素發送jsonp請求
使用<script>元素進行ajax傳輸的原因:
1、它不受同源策略的影響,因此可以使用它們從其他服務器請求數據。
2、包含JSON編碼數據的響應體會自動解碼(即執行)。
結論:當通過<script>元素調用數據時,響應內容必須用js函數名和圓括號包裹起來,而不是發送一段json數據。而且通過<script>元素只能加載get請求而不能加載post請求
2、cors(跨域資源共享 Cross-Origin Resource Sharing)
通過cors使跨域問題在get請求和post請求都可以解決
2.1、cors原理
CORS定義一種跨域訪問的機制,可以讓AJAX實現跨域訪問。CORS 允許一個域上的網絡應用向另一個域提交跨域 AJAX 請求。實現此功能非常簡單,只需由服務器發送一個響應標頭即可
2.2CORS瀏覽器支持情況
喜聞樂見、普大喜奔的支持情況,尤其是在移動終端上,除了opera Mini;
PC上的現代瀏覽器都能友好的支持,除了IE9-,不過前端工程師對這種情況早應該習慣了...
2.3 應用
假設我們頁面或者應用已在 http://www.test1.com 上了,而我們打算從 http://www.test2.com 請求提取數據。一般情況下,如果我們直接使用 AJAX 來請求將會失敗,瀏覽器也會返回“源不匹配”的錯誤,"跨域"也就以此由來。
利用 CORS,http://www.test2.com 只需添加一個標頭,就可以允許來自 http://www.test1.com 的請求,下圖是我在服務器返回中的 header() 設置,“*”號表示允許任何域向我們的服務端提交請求:
也可以設置指定的域名,如域名 http://www.test2.com ,那么就允許來自這個域名的請求:
當前我設置的header為“*”,任意一個請求過來之后服務端我們都可以進行處理&響應,那么在調試工具中可以看到其頭信息設置,其中見紅框中有一項信息是“Access-Control-Allow-Origin:* ”,表示我們已經啟用CORS。
示例代碼
https://github.com/yangxiaopingios/AjaxDemo