前后端数据交互(七)——前端跨域解决方案(全)
一、什么是跨域?
跨域就是非同源策略請(qǐng)求。
1.1、什么是同源策略?
同源策略(SOP)是一種約定,是瀏覽器最核心的也是最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到 XSS、CSFR等攻擊。
協(xié)議+域名+端口號(hào),三者都相同時(shí)就是同源,只要有一個(gè)不同就是跨域。
1.2、為什么會(huì)產(chǎn)生跨域?
很久以前,前端一般只是切圖,將設(shè)計(jì)圖實(shí)現(xiàn)成靜態(tài)網(wǎng)頁(yè),然后交給后端程序員,后端負(fù)責(zé)數(shù)據(jù)交互,將后端和前端代碼混合開(kāi)發(fā)。前端和后端是僅僅聯(lián)系在一起,不便于開(kāi)發(fā)和維護(hù),后來(lái)逐步實(shí)現(xiàn)前后端分離,把服務(wù)器拆分成三部分:
- WEB 服務(wù)器:存放靜態(tài)資源
- 后臺(tái)服務(wù)器:提供業(yè)務(wù)邏輯和數(shù)據(jù)分析。
- 圖片服務(wù)器
此時(shí)就出現(xiàn)請(qǐng)求跨域問(wèn)題了。
二、跨域解決方案
跨域解決方案總共有 9 種,它們分別為:
三、具體實(shí)現(xiàn)方案
3.1、JSONP
html頁(yè)面開(kāi)發(fā)時(shí),我們經(jīng)常會(huì)使用 script、img、link、iframe 標(biāo)簽引入對(duì)應(yīng)的資源,我們發(fā)現(xiàn)它們有個(gè)共同特點(diǎn)就是可以引入任意域名下的資源,不存在跨域問(wèn)題。因此我們利用 script 的特點(diǎn),創(chuàng)建一個(gè)帶網(wǎng)址的跨域通信。
具體的實(shí)現(xiàn)過(guò)程如圖:
原生請(qǐng)求代碼為例如下:
// 注意 -- 函數(shù)聲明放前邊 <script>function back(res){console.log(res)//返回?cái)?shù)據(jù)} </script> <script src="http://127.0.0.1:3000/login?user='111'&callback=back"></script>node服務(wù)代碼為:
var querystring = require('querystring'); var http = require('http'); var server = http.createServer(); server.on('request', function(req, res) {console.log(req.url.split)var params = querystring.parse(req.url.split('?')[1]);console.log('params',params)var fn = params.callback;// jsonp返回設(shè)置res.writeHead(200, { 'Content-Type': 'text/javascript' });res.write(fn + '(' + JSON.stringify(params) + ')');res.end(); }); server.listen('3000');運(yùn)行服務(wù)執(zhí)行成功之后就會(huì)打印出:
{callback: "back"user: "'111'" }JSONP 的缺點(diǎn):只允許處理 get 請(qǐng)求,由于請(qǐng)求的數(shù)據(jù)都暴露在url中,容易被劫持,安全性很差,所以不推薦使用。
3.2、CORS 跨域資源共享
通過(guò)設(shè)置響應(yīng)頭處理的,需要后臺(tái)配合處理。如果只是普通跨域請(qǐng)求,前端無(wú)需設(shè)置,后臺(tái)設(shè)置
Access-Control-Allow-Origin,如:
如果需要帶cookie請(qǐng)求,前端也需要設(shè)置字段。如:
// 前端設(shè)置是否帶cookie xhr.withCredentials = true;特點(diǎn):客戶端發(fā)送(ajax fetch)請(qǐng)求,后臺(tái)設(shè)置請(qǐng)求頭相關(guān)信息,允許哪些源請(qǐng)求數(shù)據(jù),需要處理 options 試探性請(qǐng)求。
3.3、proxy 代理
因?yàn)榉?wù)器間的數(shù)據(jù)交互沒(méi)有跨域限制,所以通過(guò)一個(gè)中間代理服務(wù)器請(qǐng)求目標(biāo)服務(wù)器的數(shù)據(jù),也就是前端服務(wù)器發(fā)送請(qǐng)求到代理服務(wù)器,代理服務(wù)器再請(qǐng)求目標(biāo)服務(wù)器,將數(shù)據(jù)返回給前端服務(wù)器。
我們現(xiàn)在常用的三方框架 VUE、React項(xiàng)目中跨域解決方案都使用的是代理。如config.js中代理配置如下:
proxy: { //配置跨域'/': {target: 'http://www.xxxx.com/', //線上changOrigin: true, //允許跨域pathRewrite: {'^/': ''}}, }3.4、nginx反向代理
nginx反向代理,只需要后臺(tái)配置服務(wù)就可以了,前端無(wú)需任何操作。其原理是:瀏覽器將請(qǐng)求發(fā)送到反向代理服務(wù)器,由反向代理服務(wù)器去選擇目標(biāo)服務(wù)器獲取數(shù)據(jù),再返回給瀏覽器,此時(shí)暴露的是代理服務(wù)器的地址,隱藏了真實(shí)的服務(wù)器地址。
3.5、postMessage
postMessage 是全局對(duì)象 window 的屬性之一。可以安全地實(shí)現(xiàn)跨域通信。通常,對(duì)于兩個(gè)不同頁(yè)面的腳本,只有當(dāng)執(zhí)行它們的頁(yè)面位于具有相同的協(xié)議(通常為https),端口號(hào)(443為https的默認(rèn)值),以及主機(jī) (兩個(gè)頁(yè)面的模數(shù)?Document.domain設(shè)置為相同的值) 時(shí),這兩個(gè)腳本才能相互通信。window.postMessage()?方法提供了一種受控機(jī)制來(lái)規(guī)避此限制,只要正確地使用,這種方法就很安全。
使用語(yǔ)法:
window.postMessage(data,url)具體實(shí)現(xiàn)案例如下:
// a頁(yè)面 -- http://localhost:1000/a.html <iframe id="iframe" src="http://localhost:2000/b.html" style="display:none;"></iframe> <script> var iframe = document.getElementById('iframe');iframe.onload = function() {// 向 b 傳送跨域數(shù)據(jù)iframe.contentWindow.postMessage('傳輸數(shù)據(jù)', 'http://localhost:2000');};// 接受 b 返回?cái)?shù)據(jù)window.addEventListener('message', function(e) {alert('接收返回?cái)?shù)據(jù) ---> ' + e.data);}, false); </script>// b頁(yè)面 -- http://localhost:2000/b.html <script>// 接收 a 的數(shù)據(jù)window.addEventListener('message', function(e) {alert('data from domain1 ---> ' + e.data);var data = JSON.parse(e.data);if (data) {data.number = 16;// 處理后再發(fā)回domain1window.parent.postMessage(JSON.stringify(data), 'http://localhost:1000/');}}, false); </script>3.6、webSocket
Websocket 是 html5一種新協(xié)議,實(shí)現(xiàn)瀏覽器與服務(wù)器互相通信,同時(shí)還允許跨域通訊。原生的 Websocket 可點(diǎn)擊?《WebSocket 基礎(chǔ)教程》學(xué)習(xí)更多知識(shí)。websocket api使用起來(lái)不便,我們更多地使用它的封裝版 socket.io,使用簡(jiǎn)單,易操作。
具體的實(shí)現(xiàn)方法,請(qǐng)點(diǎn)擊《一文讀懂 WebSocket 原理》。
3.7、iframe + document.domain
只能實(shí)現(xiàn)同一個(gè)主域,不同子域之間的跨域通信。
實(shí)現(xiàn)原理:兩個(gè)頁(yè)面都通過(guò) js 強(qiáng)制設(shè)置 document.domain為基礎(chǔ)主域,就實(shí)現(xiàn)了同域。
缺點(diǎn):限制較多。可作為了解就行。
3.8、iframe + location.hash
實(shí)現(xiàn)原理:a與b跨域通信,通過(guò)中間頁(yè)c來(lái)實(shí)現(xiàn),三個(gè)頁(yè)面,不同域之間可以利用 iframe 的 location.hash傳值,相同域之間直接利用 js 通信。
必須要 3 個(gè)頁(yè)面。
具體實(shí)現(xiàn):A域:a.html -> B域:b.html -> A域:c.html,a與b不同域只能通過(guò)hash值單向通信,b與c也不同域也只能單向通信,但c與a同域,所以c可通過(guò)parent.parent訪問(wèn)a頁(yè)面所有對(duì)象。
3.9、iframe + window.name
與上3.8類似,也需要3個(gè)頁(yè)面。
實(shí)現(xiàn)原理:a.html 和 proxy.html必須在一個(gè)源內(nèi),b.html在另外一個(gè)源內(nèi),a與b實(shí)現(xiàn)跨域通信,就是借助 第三個(gè) proxy.html 頁(yè)面,先把地址重新指向到同源中。proxy.html是一個(gè)空頁(yè)面,什么也不用處理。
總結(jié)
以上是生活随笔為你收集整理的前后端数据交互(七)——前端跨域解决方案(全)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: hdu 2149 巴什博弈
- 下一篇: 2021最新版谷歌浏览器百度网盘下载