初識(shí)"跨域請(qǐng)求"和"同源策略"
本章節(jié)小編初識(shí)跨域請(qǐng)求和同源策略,分享獲取新知,大家一起進(jìn)步
文章目錄
一、同源策略
二、跨域講解
三、跨域請(qǐng)求解決方案
一、同源策略
什么是同源策略
所謂同源是指,域名,協(xié)議,端口相同。
所謂“同源策略“,簡(jiǎn)單的說(shuō)就是基于安全考慮,當(dāng)前域不能訪問(wèn)其他域的東西。
拓展 什么是協(xié)議,域名,端口?
解釋:假如一個(gè)網(wǎng)址是 http://baidu.com:8080?user=name&pwd=password
http:// 是協(xié)議
baidu.com 是域名(注意:前面加上“www”即www.baidu.com不是域名)
8080 是端口
user=name&pwd=password 是地址帶的參數(shù)
舉例
如果你有一個(gè)服務(wù)器A,你所需要的script,css,php文件都在服務(wù)器A,你寫的html也在服務(wù)器A上,然后運(yùn)行,出現(xiàn)了效果,如果你想在另一臺(tái)電腦上運(yùn)行你的項(xiàng)目(注意另一臺(tái)電腦無(wú)論有沒有開啟服務(wù)器,效果還是會(huì)顯示出來(lái)的),只要把你寫在服務(wù)器A上的協(xié)議,域名,端口以及你的項(xiàng)目名稱復(fù)制下來(lái),在另一臺(tái)電腦上運(yùn)行,同樣會(huì)出現(xiàn)相同的效果,這就實(shí)現(xiàn)了同源。
簡(jiǎn)單來(lái)說(shuō),就是你的協(xié)議,域名,端口甚至項(xiàng)目名稱都一樣,不同電腦都能實(shí)現(xiàn)同樣的效果。
二、跨域講解
當(dāng)一個(gè)請(qǐng)求url的協(xié)議、域名、端口三者之間任意一個(gè)與當(dāng)前頁(yè)面url不同即為跨域
舉例
如果有兩個(gè)服務(wù)器,服務(wù)器A和服務(wù)器B,服務(wù)器A上存儲(chǔ)了php數(shù)據(jù),script,甚至是css這些文件,而你在服務(wù)器B上只寫了html,然后你所在的服務(wù)器B上動(dòng)態(tài)創(chuàng)建script,css,php數(shù)據(jù)(使用ajax請(qǐng)求),向服務(wù)器A上請(qǐng)求你想要的script,css,php數(shù)請(qǐng)求據(jù)(使用ajax)這些文件,請(qǐng)求這些文件后,你再在服務(wù)器B上運(yùn)行你的html,雖然你的地址是在服務(wù)器B上,但是你還是可以運(yùn)行效果與在服務(wù)器A上運(yùn)行的效果是一樣的,這樣就是跨域名,跨端口,跨協(xié)議,實(shí)現(xiàn)了跨域。
簡(jiǎn)單來(lái)說(shuō),就是你請(qǐng)求的文件,只要含有“src”,“href”這些屬性,你就能在其他服務(wù)器上,請(qǐng)求你所需要的文件,然后在自己的服務(wù)器上運(yùn)行,就實(shí)現(xiàn)了跨域(跨域名,跨端口,跨協(xié)議)。
三、跨域請(qǐng)求解決方案
關(guān)于跨域請(qǐng)求有很多解決方案,下面舉兩個(gè)常見的方案
①通過(guò)jsonp跨域
JSONP(JSON with Padding)是JSON的一種“使用模式”,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問(wèn)的問(wèn)題。
通常為了減輕web服務(wù)器的負(fù)載,我們把js、css,img等靜態(tài)資源分離到另一臺(tái)獨(dú)立域名的服務(wù)器上,在html頁(yè)面中再通過(guò)相應(yīng)的標(biāo)簽從不同域名下加載靜態(tài)資源,而被瀏覽器允許,基于此原理,我們可以通過(guò)動(dòng)態(tài)創(chuàng)建script,再請(qǐng)求一個(gè)帶參網(wǎng)址實(shí)現(xiàn)跨域通信
小結(jié):即是動(dòng)態(tài)創(chuàng)建
(1)原生實(shí)現(xiàn):
1
2
3
4
5
6
7
8
9
10
11
12
13
服務(wù)端返回如下(返回時(shí)即執(zhí)行全局函數(shù)):
handleCallback({"status": true, "user": "admin"})
1
(2)jquery ajax:
$.ajax({ url: 'http://www.test.com:8080/login', type: 'get', dataType: 'jsonp', // 請(qǐng)求方式為jsonp jsonpCallback: "handleCallback", // 自定義回調(diào)函數(shù)名 data: {} });
1
2
3
4
5
6
7
(3)vue.js:
this.$http.jsonp('http://www.test.com:8080/login', { params: {}, jsonp: 'handleCallback' }).then((res) => { console.log(res); })
1
2
3
4
5
6
(4)后端node.js代碼示例:
var querystring = require('querystring'); var http = require('http'); var server = http.createServer(); server.on('request', function(req, res) { var params = qs.parse(req.url.split('?')[1]); var fn = params.callback; // jsonp返回設(shè)置 res.writeHead(200, { 'Content-Type': 'text/javascript' }); res.write(fn + '(' + JSON.stringify(params) + ')'); res.end(); }); server.listen('8080'); console.log('Server is running at port 8080...');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jsonp缺點(diǎn):只能實(shí)現(xiàn)get一種請(qǐng)求。
② 跨域資源共享(CORS)
CORS是一個(gè)W3C標(biāo)準(zhǔn),全稱是"跨域資源共享"(Cross-origin resource sharing)。
它允許瀏覽器向跨源服務(wù)器,發(fā)出XMLHttpRequest請(qǐng)求,從而克服了AJAX只能同源使用的限制。
普通跨域請(qǐng)求:只服務(wù)端設(shè)置Access-Control-Allow-Origin即可,前端無(wú)須設(shè)置,若要帶cookie請(qǐng)求:前后端都需要設(shè)置。
需注意的是:由于同源策略的限制,所讀取的cookie為跨域請(qǐng)求接口所在域的cookie,而非當(dāng)前頁(yè)。
前端設(shè)置:
①原生ajax
// 前端設(shè)置是否帶cookie xhr.withCredentials = true;
1
2
例子
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容 // 前端設(shè)置是否帶cookie xhr.withCredentials = true; xhr.open('post', 'http://www.domain.com:8080/login', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('user=admin'); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { alert(xhr.responseText); } };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
②jQuery ajax
$.ajax({ ... xhrFields: { withCredentials: true // 前端設(shè)置是否帶cookie }, crossDomain: true, // 會(huì)讓請(qǐng)求頭中包含跨域的額外信息,但不會(huì)含cookie ... });
1
2
3
4
5
6
7
8
③vue框架
axios設(shè)置:
axios.defaults.withCredentials = true
1
vue-resource設(shè)置:
Vue.http.options.credentials = true
1
服務(wù)端設(shè)置
若后端設(shè)置成功,前端瀏覽器控制臺(tái)則不會(huì)出現(xiàn)跨域報(bào)錯(cuò)信息,反之,說(shuō)明沒設(shè)成功。
Java后臺(tái):
/* * 導(dǎo)入包:import javax.servlet.http.HttpServletResponse; * 接口參數(shù)中定義:HttpServletResponse response */ // 允許跨域訪問(wèn)的域名:若有端口需寫全(協(xié)議+域名+端口),若沒有端口末尾不用加'/' response.setHeader("Access-Control-Allow-Origin", "http://www.domain.com"); // 允許前端帶認(rèn)證cookie:?jiǎn)⒂么隧?xiàng)后,上面的域名不能為'*',必須指定具體的域名,否則瀏覽器會(huì)提示 response.setHeader("Access-Control-Allow-Credentials", "true"); // 提示OPTIONS預(yù)檢時(shí),后端需要設(shè)置的兩個(gè)常用自定義頭 response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
1
2
3
4
5
6
7
8
9
10
11
12
13
The best investment is in yourself
2020.04.26 記錄辰兮的第58篇博客
TCP/IP 域名注冊(cè)服務(wù)
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。