如今我們一塊兒來討論瀏覽器跨域請求數據的相關問題。說這樣可能不是很標準,由於拒絕跨域請求數據並非瀏覽器所獨有的,之因此會出現跨域請求不了數據,是由於瀏覽器基本都實現了一個叫"同源策略"的安全規範。該規範具體是什麼呢?咱們在MDN上找到了一份資料,地址以下:javascript
瀏覽器同源策略講解css
總的來講,當A網址和B網址在協議
、端口
、域名
方面存在不一樣時,瀏覽器就會啓動同源策略,拒絕A、B服務器之間進行數據請求。html
說了同源策略,紙上得來終覺淺,絕知此事要躬行,到底同源策略是怎麼體現的呢?下面我將結合代碼一步一步進行演示。前端
既然是跨域,我就假設我有兩個域名,分別是A
和localhost
,A
表示小編在阿里雲上主機域名,localhost
顧名思義就是小編的開發機器了。咱們想象這樣一個場景,在localhost
上部署一個index.html
文件,在A
服務器上部署一個簡單的spring-boot
後臺服務,並提供一個簡單的接口暴露給index.html
文件調用,最後瀏覽器請求localhost
的index.html
文件,看瀏覽器提示什麼?java
index.html
jquery
<!DOCTYPE html>
<html>
<head>
<title>測試跨域訪問</title>
<meta charset="utf-8"/>
</head>
<body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type : "get",
async : true,
url : "http://A/hello/map/getUser.json",// 請求A服務器上的接口
type : "json",
success : function(data) {
// 打印返回的數據
console.log("success,and return data is " + data);
}
});
});
</script>
<h2>hello world</h2>
</body>
</html>
複製代碼
瀏覽器上請求index.html
文件,顯示以下:git
能夠發現,請求被瀏覽器給拒絕了,提示咱們不容許跨域請求數據,很難受,怎麼解決呢?github
jsonp
解決跨域請求首先講下原理,jsonp解決跨域問題主要利用了<script>
標籤的可跨域性,也就是src
屬性中的連接地址能夠跨域訪問的特性,由於咱們常常將src
屬性值設置爲cdn的地址,已加載相關的js庫。ajax
index.html
spring
<!DOCTYPE html>
<html>
<head>
<title>測試跨域訪問</title>
<meta charset="utf-8" />
</head>
<body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type : "get",
async : true,
jsonp : "callbackName",// 後端接口參數名
jsonpCallback : "callbackFunction", // 回調函數名
url : "http://A/hello/map/getUser.json",
dataType : "jsonp", // 數據格式爲 jsonp
success : function(data) {
console.log("success");
}
});
});
</script>
<script type="text/javascript">
var callbackFunction = function(data) {
alert('接口返回的數據是:' + JSON.stringify(data));
};
</script>
</body>
</html>
複製代碼
A
服務器上的接口代碼爲:
/**
*
* The class JsonBackController.
*
* Description:該控制器返回一串簡單的json數據,json數據由一個簡單的User對象組成
*
* @author: huangjiawei
* @since: 2018年6月12日
* @version: $Revision$ $Date$ $LastChangedBy$
*
*/
@RestController
@RequestMapping(value = "/map")
public class JsonBackController {
private static final Logger logger = LoggerFactory.getLogger(JsonBackController.class);
/**
* 解決跨域請求數據
* @param response
* @param callbackName 前端回調函數名
* @return
*/
@RequestMapping(value = "getUser.json")
public void getUser(HttpServletResponse response, @RequestParam String callbackName) {
User user = new User("huangjiawei", 22);
response.setContentType("text/javascript");
Writer writer = null;
try {
writer = response.getWriter();
writer.write(callbackName + "(");
writer.write(user.toString());
writer.write(");");
} catch (IOException e) {
logger.error("jsonp響應寫入失敗! 數據:" + user.toString(), e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
logger.error("輸出流關閉異常!", e);
}
writer = null;
}
}
}
}
複製代碼
後端傳入一個參數callbackName
回調函數名,而後返回一段js代碼給前端,js代碼格式以下:
callbackName
+ ( data
) + ;
瀏覽器請求localhost
服務器上的index.html
文件,結果以下:
上面這種方式是經過jquery + jsonp
解決跨域問題的,剛剛不是說能夠用<script>
標籤的src
屬性嗎?四的。
localhost
服務器上的index.html
<!DOCTYPE html>
<html>
<head>
<title>測試跨域訪問</title>
<meta charset="utf-8" />
</head>
<body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
var callbackFunction = function(data) {
alert('接口返回的數據是:' + JSON.stringify(data));
};
</script>
<script type="text/javascript" src="http://A/hello/map/getUser.json?callbackName=callbackFunction"></script>
</body>
</html>
複製代碼
瀏覽器顯示效果和上面一致。但此處須要注意的是,src
表示引入一個js文件,因爲是直接調用接口,而接口返回的數據又恰好是一段js代碼,故能被執行。另外,第二個<script>
標籤順序不能顛倒,否則會出現callbackFunction
函數找不到的狀況。
工程代碼地址 : github.com/SmallerCode…
最後總結下,解決跨域的方案有不少種,jsonp只是其中一種,具體狀況須要具體分析。但願此文對你有幫助,謝謝閱讀,歡迎github給顆start
,麼麼噠!