為什么會(huì)發(fā)生產(chǎn)生跨域問(wèn)題空入?
[ 產(chǎn)生跨域的原因 ]
1.瀏覽器限制
2.跨域(協(xié)議,域名咖城,端口任何一個(gè)不同)
3.XHR(XMLHttpRequest)請(qǐng)求
也就是說(shuō)當(dāng)我們發(fā)送的是XMLHttpRequest請(qǐng)求不同的域名茬腿,瀏覽器就會(huì)限制訪問(wèn),那么就會(huì)產(chǎn)生跨域問(wèn)題宜雀。
[ 解決跨域問(wèn)題的思路 ]
1.改動(dòng)客戶端瀏覽器參數(shù)來(lái)解除限制 瀏覽器啟動(dòng)加入
--disable-web-security
2.Jsonp解決是XHR請(qǐng)求的問(wèn)題.
3.跨域: 被調(diào)用方支持跨域切平,調(diào)用方的隱藏請(qǐng)求
跨域問(wèn)題解決辦法
1. JSONP解決跨域
[原理]:
<script>
請(qǐng)求不受同源政策限制 :JSONP動(dòng)態(tài)創(chuàng)建<script>
標(biāo)簽,通過(guò)<script>
函數(shù)調(diào)用發(fā)出請(qǐng)求辐董,返回值是也是js悴品,函數(shù)名callback參數(shù)的值,函數(shù)參數(shù)是返回的json對(duì)象()
[弊端]:1.只支持Get請(qǐng)求2.發(fā)送到不是XHR請(qǐng)求
[jsonp請(qǐng)求實(shí)現(xiàn)]
$.ajax({
url: 'url",
dataType: "jsonp",
jsonp: "callback",
cache: true,
success: function(json) {
result = json;
}
});
[jsonp請(qǐng)求實(shí)現(xiàn)原理]
//動(dòng)態(tài)創(chuàng)建script標(biāo)簽
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
// 回調(diào)函數(shù)-獲取數(shù)據(jù)
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
2. 跨域解決方案CORS
CORS是一個(gè)W3C標(biāo)準(zhǔn)简烘,全稱是”跨域資源共享”(Cross-origin resource sharing)苔严。CORS需要瀏覽器和服務(wù)器同時(shí)支持。目前孤澎,所有瀏覽器都支持該功能届氢,IE瀏覽器不能低于IE10。
它允許瀏覽器向跨源服務(wù)器覆旭,發(fā)出XMLHttpRequest請(qǐng)求退子,從而克服了AJAX只能同源使用的限制岖妄。整個(gè)CORS通信過(guò)程,都是瀏覽器自動(dòng)完成寂祥,不需要用戶參與衣吠。對(duì)于開發(fā)者來(lái)說(shuō),CORS通信與同源的AJAX通信沒(méi)有差別壤靶,代碼完全一樣。瀏覽器一旦發(fā)現(xiàn)AJAX請(qǐng)求跨源惊搏,就會(huì)自動(dòng)添加一些附加的頭信息贮乳,有時(shí)還會(huì)多出一次附加的請(qǐng)求,但用戶不會(huì)有感覺(jué)恬惯。因此向拆,實(shí)現(xiàn)CORS通信的關(guān)鍵是服務(wù)器。只要服務(wù)器實(shí)現(xiàn)了CORS接口酪耳,就可以跨源通信浓恳。
[簡(jiǎn)單請(qǐng)求-post請(qǐng)求]
解決:被調(diào)用放服務(wù)端設(shè)置Access-Control-Allow-Origin
被調(diào)用放服務(wù)端設(shè)置Access-Control-Allow-Methods
res.addHeader("Access-Control-Allow-Origin", "*") //允許所有域名可以跨域調(diào)用
res.addHeader("Access-Control-Allow-Methods", "*") //允許所有請(qǐng)求方式跨域調(diào)用
[非簡(jiǎn)單請(qǐng)求-帶cookie的請(qǐng)求]
$.ajax({
type: "get",
url: "url",
xhrFields: {
withCredentials: true
},
success: function(json) {
result = json;
}
});
解決:帶cookie時(shí)origin必須全匹配, 不能使用 *
被調(diào)用放服務(wù)端增加設(shè)置Access-Control-Allow-Credentials
res.addHeader("Access-Control-Allow-Origin", "localhost:8081")
res.addHeader("Access-Control-Allow-Methods", "*")
res.addHeader("Access-Control-Allow-Credentials", "true") //enable cookie
[非簡(jiǎn)單請(qǐng)求-帶header的請(qǐng)求]
$.ajax({
type: "get",
url: 'url",
headers: {
"x-header1": "AAA"
},
beforeSend: function(xhr) {
xhr.setRequestHeader("x-header2", "BBB")
},
success: function(json) {
result = json;
}
});
解決:帶cookie時(shí)origin必須全匹配碗暗, 不能使用 *
被調(diào)用放服務(wù)端增加設(shè)置Access-Control-Allow-Header
res.addHeader("Access-Control-Allow-Origin", "*")
res.addHeader("Access-Control-Allow-Methods", "*")
res.addHeader("Access-Control-Allow-Header", "content-Type,x-header1,x-header2")
綜上所述:
//帶cookie的時(shí)候颈将,origin必須是全匹配,不能使用*
String origin = req.getHeader("Origin");
if (!org.springframework.util.StringUtils.isEmpty(origin)) {
res.addHeader("Access-Control-Allow-Origin", origin);
}
res.addHeader("Access-Control-Allow-Methods", "*");
// 支持所有自定義頭和預(yù)檢命令(非簡(jiǎn)單請(qǐng)求會(huì)有預(yù)檢命令)
String headers = req.getHeader("Access-Control-Request-Headers");
if (!org.springframework.util.StringUtils.isEmpty(headers)) {
res.addHeader("Access-Control-Allow-Headers", headers);
}
res.addHeader("Access-Control-Max-Age", "3600");
// enable cookie
res.addHeader("Access-Control-Allow-Credentials", "true");
3. Nginx代理
如果我們請(qǐng)求的時(shí)候還是用前端的域名言疗,Nginx幫我們把這個(gè)請(qǐng)求轉(zhuǎn)發(fā)到真正的后端域名上
[Nginx配置]
server{
# 監(jiān)聽9000端口
listen 9000;
# 域名是localhost
server_name localhost;
#凡是localhost:9000/api這個(gè)樣子的晴圾,都轉(zhuǎn)發(fā)到真正的服務(wù)端地址http://localhost:9001
location ^~ /api {
proxy_pass http://localhost:9001;
}
}
簡(jiǎn)單請(qǐng)求&非簡(jiǎn)單請(qǐng)求
只要同時(shí)滿足以下兩大條件,就屬于簡(jiǎn)單請(qǐng)求,其余屬于非簡(jiǎn)單請(qǐng)求
(1) 請(qǐng)求方法是以下三種方法之一:HEAD噪奄、GET死姚、POST
(2)HTTP的頭信息不超出以下幾種字段(無(wú)自定義頭):
Accept Accept-Language Content-Language Last-Event-ID
(3)Content-Type:只限于三個(gè)值
application/x-www-form-urlencoded multipart/form-data text/plain
碼字不易,如果覺(jué)得對(duì)您有幫助勤篮,給個(gè)贊給一個(gè)小小的鼓勵(lì)吧 (.)!