文章目錄
- 前言
- 一、為什么會跨域
- 1. 什么是源
- 2. URL結構
- 3. 同源不同源舉🌰
- 同源例子
- 不同源例子
- 4. 瀏覽器為什么需要同源策略
- 5. 常規前端請求跨域
- 二、前端解決方案
- jsonp
- webpack-dev-server
- document.domain
- 三、后端解決方案
- Http 協議CORS頭
- SpringCloud設定跨域
- Koa設定跨域
- 四、運維解決方案
- 五、總結
- 參考鏈接
前言
跨域問題一直是前端的一大難題,從前端出道到至今,無論是自己還是身邊的同事,以及網上前端朋友都被這個問題困擾著,
尤其最近寫了一個網路封裝,用戶提出最多的便是跨域問題,解釋了很多次,都寫在這里吧,以后自己忘了也可以看看,總結一下,
貼上標準的前端跨域報錯(SpringBoot后臺):
Access to XMLHttpRequest at '…' from origin '…' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
一、為什么會跨域
說到跨域不得不談的就是瀏覽器的同源策略,跨域也是因為瀏覽器這個機制引起的,這個機制的存在還是在于安全,
1. 什么是源
Web內容的源由用于訪問它的URL 的方案(協議),主機(域名)和埠定義,只有當方案,主機和埠都匹配時,兩個物件具有相同的起源,
同源不同源一句話就可以判斷:就是url中 scheme host port 都相同即為同源,
下面認識下url 結構中的這三個部分,
2. URL結構
URL 代表著是統一資源定位符(Uniform Resource Locator),URL 無非就是一個給定的獨特資源在 Web 上的地址,
URL有如下結構組成:
- Schme 或者 Protocol

- Domain Name 也叫做host域名

- port 埠號

-
Parameters引數

-
Anchor 錨點,一般用于定位位置

3. 同源不同源舉🌰
舉一下同源不同源的例子,便于
同源例子
| 例子 | 原因 |
|---|---|
| http://example.com/app1/index.html http://example.com/app2/index.html | 相同的 scheme http 和host |
| http://Example.com:80 http://example.com | http 默認80埠所以同源 |
不同源例子
| 例子 | 原因 |
|---|---|
| http://example.com/app1 https://example.com/app2 | 不同的協議 |
| http://example.com http://myapp.example.com | 不同的host |
| http://example.com http://example.com:8080 | 不同的埠 |
4. 瀏覽器為什么需要同源策略
同源策略是一個重要的安全策略,它用于限制一個origin的檔案或者它加載的腳本如何能與另一個源的資源進行互動,它能幫助阻隔惡意檔案,減少可能被攻擊的媒介,
5. 常規前端請求跨域
在沒有前后端分離的時候,跨域問題往往是很少的,因為前后端都部署到一起,現在前后端分離不管vue /react 面臨跨域請求的問題,
下面是參考官網描述的一張圖來解釋跨域:

跨源域資源共享(CORS)機制允許 Web 應用服務器進行跨源訪問控制,從而使跨源資料傳輸得以安全進行,現代瀏覽器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch)使用 CORS,以降低跨源 HTTP 請求所帶來的風險,
二、前端解決方案
jsonp
JSONP的原理非常簡單,就是HTML標簽中,很多帶src屬性的標簽都可以跨域請求內容,比如我們熟悉的img圖片標簽,同理,script標簽也可以,可以利用script標簽來執行跨域的javascript代碼,通過這些代碼,我們就能實作前端跨域請求資料,
jsonp 可以在前端解決跨域問題,但是只是針對于get請求,實作方式可以參考一些npm 第三方庫實作,jquery 也是帶的,
可以在npm 搜下jsonp 庫實作,非常簡單,

webpack-dev-server
前端無論是vue專案還是react 專案大多數都會以webpack-dev-server 來運行,webpack-dev-server 可以設定代理,前端可以在開發環境設定代理解決跨域問題,
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '' },
changeOrigin: true,
},
}
vue-cli、create-react-app、umi 等腳手架找到webpack devserver配置位置配上即可,
注意: 只限在開發環境,生產環境需要web 服務器同樣原理代即可,下面會說明怎么用,
document.domain
利用document.domain 可以修改 訪問頁面的域,多用在父子關系的域,子域可以設定document.domain等于父域,從而解決同父域跨域問題,
舉例子:
www.ios.xingyu.com 訪問 www.web.xingyu.com 跨域,可以利用 document.domain 設定成 www.xingyu.com
三、后端解決方案
后端框架也很多,實作原理差不多,都是修改下相應頭,以常用的Java SpringCloud 和nodejs koa 框架為例,
Http 協議CORS頭
跨域其實也是http層面上可以解決的問題,后端解決也是比較簡單的,也是專案常見的解決手法,
CORS (Cross-Origin Resource Sharing,跨域資源共享)是一個系統,它由一系列傳輸的HTTP頭組成,這些HTTP頭決定瀏覽器是否阻止前端 JavaScript 代碼獲取跨域請求的回應,
同源安全策略 默認阻止“跨域”獲取資源,但是 CORS 給了web服務器這樣的權限,即服務器可以選擇,允許跨域請求訪問到它們的資源,
- Access-Control-Allow-Origin
指示請求的資源能共享給哪些域, - Access-Control-Allow-Credentials
指示當請求的憑證標記為 true 時,是否回應該請求, - Access-Control-Allow-Headers
用在對預請求的回應中,指示實際的請求中可以使用哪些 HTTP 頭, - Access-Control-Allow-Methods
指定對預請求的回應中,哪些 HTTP 方法允許訪問請求的資源, - Access-Control-Expose-Headers
指示哪些 HTTP 頭的名稱能在回應中列出, - Access-Control-Max-Age
指示預請求的結果能被快取多久, - Access-Control-Request-Headers
用于發起一個預請求,告知服務器正式請求會使用那些 HTTP 頭, - Access-Control-Request-Method
用于發起一個預請求,告知服務器正式請求會使用哪一種 HTTP 請求方法, - Origin
指示獲取資源的請求是從什么域發起的,
SpringCloud設定跨域
在跨域過濾器里配置一下跨域頭部,* 是通配符即允許所有,
@Configuration
public class GatewayCorsConfiguation {
@Bean
public CorsFilter corsFilter(){
// 初始化cors配置物件
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true); // 允許使用cookie,但是使用cookie是addAllowedOrigin必須是具體的地址,不能是*
// configuration.addAllowedOrigin("*");
configuration.addAllowedOrigin("http://manage.leyou.com");
configuration.addAllowedMethod("*"); //允許的請求方式,get,put,post,delete
configuration.addAllowedHeader("*");//允許的頭資訊
//初始化cors的源物件配置
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**",configuration);
//3.回傳新的CorsFilter.
return new CorsFilter(corsConfigurationSource);
}
}
Koa設定跨域
koa 是插件機制,設定更簡單,使用跨域插件即可,
import cors from "koa2-cors";
app.use(cors());
四、運維解決方案
運維解決我只會一點ngnix ,其他web 服務器就不說了,原理同webpack-dev-server 設定代理轉發解決跨域問題,
步驟:
- 前端和運維商量好協議路徑代理規則,比如/api 代表域名
- 前端配置webpack -dev -server 代理
- 服務器利用ngnix 配置相同轉發代理
ngnix 配置代理解決跨域配置:
...
location /api {
proxy_pass https://b.test.com; # 設定代理服務器的協議和地址
}
...

五、總結
在作業中,大多數還是利用后端或者ngnix 代理來解決,前端可以在開發中臨時配置解決問題,
參考鏈接
- https://developer.mozilla.org/zh-CN/docs/Glossary/CORS
- https://developer.mozilla.org/zh-CN/docs/Glossary/Origin
- https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/414027.html
標籤:其他
上一篇:【Python自動化測驗11】模塊、包與路徑知識合集
下一篇:OSPF實驗
