鏈接:https://www.imooc.com/article/291931
一匪蝙、什么是跨域易结?
在前端領(lǐng)域中,跨域是指瀏覽器允許向服務(wù)器發(fā)送跨域請求胸竞,從而克服Ajax只能同源使用的限制斥季。
什么是同源策略训桶?
同源策略是一種約定,由Netscape公司1995年引入瀏覽器酣倾,它是瀏覽器最核心也最基本的安全功能舵揭,如果缺少了同源策略,瀏覽器很容易受到XSS躁锡、CSFR等攻擊午绳。所謂同源是指"協(xié)議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址映之,也非同源拦焚。
同源策略限制以下幾種行為:
Cookie、LocalStorage 和 IndexDB 無法讀取
DOM和JS對象無法獲得
AJAX 請求不能發(fā)送
二杠输、常見的跨域場景
URL說明是否允許通信
http://www.domain.com/lab/c.js
同一域名赎败,不同文件或路徑允許
http://www.domain.com:8000/a.js
同一域名,不同端口不允許
http://www.domain.com/a.js
https://www.domain.com/b.js
同一域名蠢甲,不同協(xié)議不允許
http://www.domain.com/a.js
http://192.168.4.12/b.js
域名和域名對應(yīng)相同ip不允許
http://www.domain.com/a.js
http://x.domain.com/b.js
http://domain.com/c.js
主域相同僵刮,子域不同不允許
http://www.domain1.com/a.js
http://www.domain2.com/b.js
不同域名不允許
三、9種跨域解決方案
1鹦牛、JSONP跨域
jsonp的原理就是利用<script>搞糕,img,link,iframe標(biāo)簽沒有跨域限制,通過<script>標(biāo)簽src屬性曼追,發(fā)送帶有callback參數(shù)的GET請求窍仰,服務(wù)端將接口返回數(shù)據(jù)拼湊到callback函數(shù)中,返回給瀏覽器礼殊,瀏覽器解析執(zhí)行辈赋,從而前端拿到callback函數(shù)返回的數(shù)據(jù)鲫忍。
jsonp的缺點:只能發(fā)送get一種請求。
2钥屈、跨域資源共享(CORS)
3、nginx代理跨域
nginx代理跨域坝辫,實質(zhì)和CORS跨域原理一樣篷就,通過配置文件設(shè)置請求響應(yīng)頭Access-Control-Allow-Origin…等字段。
1)nginx配置解決iconfont跨域
??瀏覽器跨域訪問js近忙、css竭业、img等常規(guī)靜態(tài)資源被同源策略許可,但iconfont字體文件(eot|otf|ttf|woff|svg)例外及舍,此時可在nginx的靜態(tài)資源服務(wù)器中加入以下配置未辆。
location / {
? add_header Access-Control-Allow-Origin *;
}
2)nginx反向代理接口跨域
跨域問題:同源策略僅是針對瀏覽器的安全策略。服務(wù)器端調(diào)用HTTP接口只是使用HTTP協(xié)議锯玛,不需要同源策略咐柜,也就不存在跨域問題。
實現(xiàn)思路:通過Nginx配置一個代理服務(wù)器域名與domain1相同攘残,端口不同)做跳板機(jī)拙友,反向代理訪問domain2接口,并且可以順便修改cookie中domain信息歼郭,方便當(dāng)前域cookie寫入遗契,實現(xiàn)跨域訪問
4、nodejs中間件代理跨域
?1)?node中間件實現(xiàn)跨域代理病曾,原理大致與nginx相同牍蜂,都是通過啟一個代理服務(wù)器,實現(xiàn)數(shù)據(jù)的轉(zhuǎn)發(fā)泰涂,也可以通過設(shè)置cookieDomainRewrite參數(shù)修改響應(yīng)頭中cookie中域名鲫竞,實現(xiàn)當(dāng)前域的cookie寫入,方便接口登錄認(rèn)證
2)? ?node + vue + webpack + webpack-dev-server搭建的項目负敏,跨域請求接口贡茅,直接修改webpack.config.js配置。開發(fā)環(huán)境下其做,vue渲染服務(wù)和接口代理服務(wù)都是webpack-dev-server同一個顶考,所以頁面與代理接口之間不再跨域
5、document.domain + iframe跨域
此方案僅限主域相同妖泄,子域不同的跨域應(yīng)用場景驹沿。實現(xiàn)原理:兩個頁面都通過js強(qiáng)制設(shè)置document.domain為基礎(chǔ)主域,就實現(xiàn)了同域蹈胡。
1)父窗口:(http://www.domain.com/a.html)
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
? ? document.domain = 'domain.com';
? ? var user = 'admin';
</script>
1)子窗口:(http://child.domain.com/a.html)
<script>
? ? document.domain = 'domain.com';
? ? // 獲取父窗口中變量
? ? console.log('get js data from parent ---> ' + window.parent.user);
</script>
6渊季、location.hash + iframe跨域
實現(xiàn)原理: a欲與b跨域相互通信朋蔫,通過中間頁c來實現(xiàn)。 三個頁面却汉,不同域之間利用iframe的location.hash傳值驯妄,相同域之間直接js訪問來通信。
具體實現(xiàn):A域:a.html -> B域:b.html -> A域:c.html合砂,a與b不同域只能通過hash值單向通信青扔,b與c也不同域也只能單向通信,但c與a同域翩伪,所以c可通過parent.parent訪問a頁面所有對象微猖。
7、window.name + iframe跨域
??window.name屬性的獨特之處:name值在不同的頁面(甚至不同域名)加載后依舊存在缘屹,并且可以支持非常長的 name 值(2MB)凛剥。
8、postMessage跨域
??postMessage是HTML5 XMLHttpRequest Level 2中的API轻姿,且是為數(shù)不多可以跨域操作的window屬性之一犁珠,它可用于解決以下方面的問題:
頁面和其打開的新窗口的數(shù)據(jù)傳遞
多窗口之間消息傳遞
頁面與嵌套的iframe消息傳遞
上面三個場景的跨域數(shù)據(jù)傳遞
用法:postMessage(data,origin)方法接受兩個參數(shù):
data: html5規(guī)范支持任意基本類型或可復(fù)制的對象,但部分瀏覽器只支持字符串踢代,所以傳參時最好用JSON.stringify()序列化盲憎。
origin: 協(xié)議+主機(jī)+端口號,也可以設(shè)置為
9胳挎、WebSocket協(xié)議跨域
WebSocket protocol是HTML5一種新的協(xié)議饼疙。它實現(xiàn)了瀏覽器與服務(wù)器全雙工通信,同時允許跨域通訊慕爬,是server push技術(shù)的一種很好的實現(xiàn)窑眯。
原生WebSocket API使用起來不太方便,我們使用Socket.io医窿,它很好地封裝了webSocket接口磅甩,提供了更簡單、靈活的接口姥卢,也對不支持webSocket的瀏覽器提供了向下兼容卷要。