是誰(shuí)引起的跨域?
跨域是瀏覽器(瀏覽器內(nèi)核)的安全檢測(cè)行為而并非是服務(wù)器端行為。
真正跨域作用的地方在于瀏覽器接收到服務(wù)器端響應(yīng)的數(shù)據(jù)后,通過檢查是否滿足跨域的條件要求而決定是否對(duì)數(shù)據(jù)進(jìn)行攔截丟棄的過程。
跨域的必要條件
- 瀏覽器限制: 即瀏覽器對(duì)跨域行為進(jìn)行檢測(cè)和阻止
-
觸發(fā)跨域的三要素:
不同協(xié)議、不同域名、不同端口,滿足其一 - 發(fā)起的是xhr請(qǐng)求: 即發(fā)起的是XMLHttpRequest類型的請(qǐng)求
跨域的幾種解決方案
- 開發(fā)階段
- 解除瀏覽器安全限制(針對(duì)第一個(gè)必要條件)
- window
在chrome瀏覽器右鍵屬性中的目標(biāo)中添加--args --disable-web-security --user-data-dir
瀏覽器屬性配置圖
重新打開瀏覽器顯示下圖提示,表示成功
解除安全限制提示
- linux
直接運(yùn)行命令行open -a "Google Chrome" --args --disable-web-security --user-data-dir
-
本地設(shè)置node代理服務(wù)器(針對(duì)第二個(gè)必要條件)
很多框架的cli都已經(jīng)整合了本地代理服務(wù)器來進(jìn)行跨域,配置也更加簡(jiǎn)單。 以vue-cli為例:
在config/index.js中簡(jiǎn)單配置即可
原理:vue-cli跨域設(shè)置
在本地配置代理服務(wù)器 項(xiàng)目就直接請(qǐng)求本地服務(wù)器,這樣就完美的避過了上面寫的第二個(gè)必要條件。然后本地服務(wù)器再和遠(yuǎn)程服務(wù)器進(jìn)行通信來獲取數(shù)據(jù)。
跨域是瀏覽器的限制行為,服務(wù)器通信不存在跨域。
- 生產(chǎn)階段
-
jsonp請(qǐng)求(針對(duì)第三個(gè)必要條件)
JSONP 方案原理就是通過動(dòng)態(tài)創(chuàng)建script標(biāo)簽,利用標(biāo)簽內(nèi)src屬性發(fā)送同步請(qǐng)求。本質(zhì)就是利用script標(biāo)簽加載遠(yuǎn)程js的特性,理論上來說有src屬性的標(biāo)簽都可以。
通過瀏覽器控制臺(tái)Network選項(xiàng)查看發(fā)現(xiàn),JSONP發(fā)出去的請(qǐng)求類型是script,img標(biāo)簽src屬性發(fā)出去的請(qǐng)求類型是JSON,他們都不是xhr, 因?yàn)闆]有形成跨域的第三個(gè)條件,因此不會(huì)觸發(fā)瀏覽器跨域檢查策略。
雖然JSONP能處理跨域問題,但其實(shí)它存在很多弊端,主要如下:
- 需要服務(wù)器端修改代碼支持: 服務(wù)器端不再返回json格式,而是返回固定格式的回調(diào)函數(shù)
- 只支持GET請(qǐng)求: 即使設(shè)置了請(qǐng)求類型為POST也無效,只支持GET
- 發(fā)送的不是XHR請(qǐng)求: 正因?yàn)檫@點(diǎn)才支持了跨域,然而也丟失了xhr強(qiáng)大的功能
-
服務(wù)器端配置
添加允許訪問的域名白名單
// 允許跨域的域名,設(shè)置*表示允許除帶Cookies信息的所有域名
res.addHeader("Access-Control-Allow-Origin", "http://localhost:8081");
這樣在xhr請(qǐng)求的時(shí)候,瀏覽器判斷請(qǐng)求源域名在允許訪問的域名中,就不會(huì)進(jìn)行請(qǐng)求數(shù)據(jù)的攔截。所以就不會(huì)存在跨域問題。

請(qǐng)求頭

響應(yīng)頭


