
## 一、什么是跨域訪問
說到跨域訪問,必須先解釋一個名詞:同源策略。所謂同源策略就是在瀏覽器端出于安全考量,向服務端發起請求必須滿足:協議相同、Host(ip)相同、端口相同的條件,否則訪問將被禁止,該訪問也就被稱為跨域訪問。
雖然跨域訪問被禁止之后,可以在一定程度上提高了應用的安全性,但也為開發帶來了一定的麻煩。比如:我們開發一個前后端分離的易用,頁面及js部署在一個主機的nginx服務中,后端接口部署在一個tomcat應用容器中,當前端向后端發起請求的時候一定是不符合同源策略的,也就無法訪問。那么我們如何解決這個問題?就是本文需要向大家說明的內容。
## 二、跨域訪問的解決方案有哪些?
### 2.1.第一類方案:前端解決方案
雖然瀏覽器對于不符合同源策略的訪問是禁止的,但是仍然存在例外的情況,如以下資源引用的標簽不受同源策略的限制:
* html的script標簽
* html的link標簽
* html的img標簽
* html的iframe標簽:對于使用jsp、freemarker開發的項目,這是實現跨域訪問最常見的方法,
除了基于HTML本身的特性實現跨域訪問,我們還可以使用jsonp、window的postMessage實現跨域訪問。這些都是前端實現跨域訪問的方式。
### 2.2.第二類方案:使用代理
實際上對跨域訪問的支持在服務端實現起來更加容易,最常用的方法就是通過代理的方式,如:
* nginx或haproxy代理跨域
* nodejs中間件代理跨域
其實實現代理跨域的邏輯非常簡單:就是在不同的資源服務:js資源、html資源、css資源、接口數據資源服務的前端搭建一個中間層,所有的瀏覽器及客戶端訪問都通過代理轉發。所以在瀏覽器、客戶端看來,它們訪問的都是同一個ip、同一個端口的資源,從而符合同源策略實現跨域訪問。

### 2.3 第三類方案:CORS
跨域資源共享(CORS):通過修改Http協議header的方式,實現跨域。說的簡單點就是,通過設置HTTP的響應頭信息,告知瀏覽器哪些情況在不符合同源策略的條件下也可以跨域訪問,瀏覽器通過解析Http協議中的Header執行具體判斷。具體的Header如下:
**CROS跨域常用header**
Access-Control-Allow-Origin: 允許哪些ip或域名可以跨域訪問
Access-Control-Max-Age: 表示在多少秒之內不需要重復校驗該請求的跨域訪問權限
Access-Control-Allow-Methods: 表示允許跨域請求的HTTP方法,如:GET,POST,PUT,DELETE
Access-Control-Allow-Headers: 表示訪問請求中允許攜帶哪些Header信息,如:`Accept`、`Accept-Language`、`Content-Language`、`Content-Type`
## 三、SpringBoot下實現CORS的四種方式
為大家介紹四種實現CORS的方法,兩種是全局配置,兩種是局部接口生效的配置。一般來說,SpringBoot項目采用其中一種方式實現CORS即可。
### 3.1.使用CorsFilter進行全局跨域配置
```
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//開放哪些ip、端口、域名的訪問權限,星號表示開放所有域
config.addAllowedOrigin("*");
//是否允許發送Cookie信息
config.setAllowCredentials(true);
//開放哪些Http方法,允許跨域訪問
config.addAllowedMethod("GET","POST", "PUT", "DELETE");
//允許HTTP請求中的攜帶哪些Header信息
config.addAllowedHeader("*");
//暴露哪些頭部信息(因為跨域訪問默認不能獲取全部頭部信息)
config.addExposedHeader("*");
//添加映射路徑,“/**”表示對所有的路徑實行全局跨域訪問權限的設置
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}
```
### 3.2. 重寫WebMvcConfigurer的addCorsMappings方法(全局跨域配置)
```
@Configuration
public class GlobalCorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //添加映射路徑,“/**”表示對所有的路徑實行全局跨域訪問權限的設置
.allowedOrigins("*") //開放哪些ip、端口、域名的訪問權限
.allowCredentials(true) //是否允許發送Cookie信息
.allowedMethods("GET","POST", "PUT", "DELETE") //開放哪些Http方法,允許跨域訪問
.allowedHeaders("*") //允許HTTP請求中的攜帶哪些Header信息
.exposedHeaders("*"); //暴露哪些頭部信息(因為跨域訪問默認不能獲取全部頭部信息)
}
};
}
}
```
### 3.3.使用CrossOrigin注解(局部跨域配置)
* 將CrossOrigin注解加在Controller層的方法上,該方法定義的RequestMapping端點將支持跨域訪問
* 將CrossOrigin注解加在Controller層的類定義處,整個類所有的方法對應的RequestMapping端點都將支持跨域訪問
```
@RequestMapping("/cors")
@ResponseBody
@CrossOrigin(origins = "http://localhost:8080", maxAge = 3600)
public String cors( ){
return "cors";
}
```
### 3.4 使用HttpServletResponse設置響應頭(局部跨域配置)
這種方式略顯麻煩,不建議在SpringBoot項目中使用。
```
@RequestMapping("/cors")
@ResponseBody
public String cors(HttpServletResponse response){
//使用HttpServletResponse定義HTTP請求頭,最原始的方法也是最通用的方法
response.addHeader("Access-Control-Allow-Origin", "http://localhost:8080");
return "cors";
}
```
## 四、實現與測試
在SpringBoot**項目外**隨便定義一個HTML,并寫代碼觸發如下的ajax代碼。(觸發過程我就不寫了,定義一個按鈕加一個監聽函數即可)。以下是跨域AJAX請求驗證的核心代碼:
```
$.ajax({
url: 'http://localhost:8090/cors',
type: "POST",
xhrFields: {
withCredentials: true //允許發送Cookie信息
},
success: function (data) {
alert("跨域請求配置成功")
},
error: function (data) {
alert("跨域請求配置失敗")
}
})
```
* 跨域請求配置成功表示:我們的跨域配置生效,ajax請求可以正確訪問服務端接口。
* 跨域請求配置失敗表示:我們的跨域配置未生效,請參照檢查第三節檢查各項配置是否正確。
- 核心內容介紹
- 問題Q&A匯總
- 本文檔已達38萬字
- 聯系作者-代碼工具獲取
- 作者的其他作品推薦
- vue深入淺出系列
- Spring Security-JWT-OAuth2一本通
- 實戰前后端分離RBAC權限管理系統
- 實戰SpringCloud微服務從青銅到王者
- 第一章 spring boot 2.x基礎及概念入門
- 1.1.spring boot 產生的背景及其優勢
- 1.2.helloworld及項目結構介紹
- 1.3.需要先了解的核心概念
- 1.4.提高開發效率必備工具lombok
- 1.5.IDEA環境下的熱加載與熱部署
- 1.6.開發過程中常用IDEA插件
- 第二章 RESTful接口實現與測試
- 2.1.RESTful接口與http協議狀態表述
- 2.2.1.Spring常用注解及基礎講解
- 2.2.2.常用注解開發一個RESTful接口
- 2.2.3.配合前端axios傳參總結
- 2.3.1 JSON數據處理與PostMan測試
- 2.3.2. Jackson全局配置
- 2.4.使用Mockito編碼完成接口測試
- 2.5. 使用Swagger2構建API文檔
- 2.6.接口文檔多種格式導出離線閱讀
- 2.7.Swagger3-即OpenAPI使用
- 第三章 spring boot 配置管理
- 3.1.結合源碼講解bean自動裝配原理
- 3.2.詳解YAML語法及占位符語法
- 3.3.YAML配置綁定變量兩種方式
- 3.4.配置屬性值數據綁定校驗
- 3.5.加載額外配置文件的兩種方式
- 3.6.使用SpEL表達式綁定配置項
- 3.7.profile不同環境使用不同配置
- 3.8.配置及配置文件的加載優先級
- 3.9.配置文件敏感字段加密
- 第四章 整合數據庫開發框架
- 4.1.整合Spring JDBC操作數據
- 4.2 Spring JDBC多數據源的實現
- 4.3.Spring JDBC JTA實現分布式事務
- 4.4.主流ORM持久層框架選型
- 4.5.java bean的賦值轉換
- 4.6.整合Spring Data JPA操作數據
- 4.6.1.SpringDataJPA實現分頁排序
- 4.7.Spring data JPA的多數據源實現
- 4.8.JPA+atomikos實現分布式事務
- 4.9.1.整合MybatisGenerator操作數據
- 4.9.2.整合mybatisPlus操作數據庫
- 4.10.Mybatis開發最佳實踐總結
- 4.11.Spring mybatis的多數據源實現
- 4.12.1.mybatis+atomikos實現分布式事務
- 4.12.2.mybatisplus+atomikos實現分布式事務
- 4.13.Spring事務與分布式事務
- 4.14.一行代碼實現RESTFul接口
- 4.15.一鍵生成數據庫文檔
- 第五章 整合靜態資源與模板引擎
- 5.1.1.webjars與靜態資源
- 5.1.2.訪問jar內部靜態資源
- 5.2.模板引擎選型與未來趨勢
- 5.3.web應用開發之整合jsp
- 5.4.web應用開發之整合freemarker
- 5.5.web應用開發之整合thymeleaf
- 5.6.thymeleaf基礎語法講解
- 5.7.thymeleaf內置對象與工具類
- 5.8.公共片段(標簽)與內聯js
- 第六章 生命周期內的攔截過濾與監聽
- 6.1.Servlet域對象與屬性變化監聽
- 6.2.Servlet過濾器的實現
- 6.3.spring攔截器及請求鏈路說明
- 6.4.自定義事件的發布與監聽
- 6.5.應用啟動的監聽
- 6.6.類初始化監聽
- 第七章 嵌入式容器的配置與應用
- 7.1.嵌入式容器的運行參數配置
- 7.2.為Web容器配置HTTPS
- 7.3.切換到jetty&undertow容器
- 7.4.打war包部署到外置tomcat容器
- 第八章 統一全局異常處理
- 8.1.設計一個優秀的異常處理機制
- 8.2.自定義異常和相關數據結構
- 8.3.通用全局異常處理邏輯
- 8.4.服務端數據校驗異常處理邏輯
- 8.5.AOP完美處理頁面跳轉異常
- 第九章 日志框架與全局日志管理
- 9.1.日志框架的體系結構
- 9.2.logback日志框架配置
- 9.3.1.log4j2日志框架整合與使用
- 9.3.2.log4j2異步日志配置
- 9.4.攔截器實現統一訪問日志
- 第十章 異步任務與定時任務
- 10.1.實現Async異步任務
- 10.2.為異步任務規劃線程池
- 10.3.通過@Scheduled實現定時任務
- 10.4.quartz簡單定時任務(內存持久化)
- 10.5.quartz動態定時任務(數據庫持久化)
- 10.6.可觀測異步任務線程池
- 第十一章 redis緩存與session共享
- 11.1.使用docker安裝redis
- 11.2.redis數據結構與應用場景
- 11.3.單例哨兵及集群模式整合
- 11.4.使用redisTemplate操作數據
- 11.5.使用Redis Repository操作數據
- 11.6.spring cache緩存基本用法
- 11.7.1.詳述緩存聲明式注解的使用
- 11.7.2.EhCache緩存
- 11.8.緩存雪崩穿透等解決方案
- 11.9.集群多節點應用session共享
- 11.10.介紹redis分布式鎖
- 11.11.RedisLockRegistry分布式鎖
- 11.12.使用redisson實現分布式鎖
- 第十二章 整合分布式文件系統
- 12.1.文件本地上傳與提供訪問服務
- 12.2.MinIO簡介與選型介紹
- 12.3.MinIO的安裝與基礎用法
- 12.4.整合MinIO的JavaSDK
- 12.5.fastdfs簡介及架構說明
- 12.6.使用docker安裝fastdfs
- 12.7.開發一個自定義fastdfs-starter
- 12.8.整合fastdfs操作文件數據
- 第十三章 服務器推送技術
- 13.1.主流服務器推送技術說明
- 13.2.服務端推送事件SSE
- 13.3.雙向實時通信websocket
- 第十四章 郵件發送的整合與使用
- 14.1.基礎協議及郵件配置整合
- 14.2.發送html和基于模板的郵件
- 14.3.發送帶附件和內聯附件郵件
- 第十五章 應用程序監控管理
- 15.1.Actuator應用監控快速入門
- 15.2.Actuator服務保護緩存及跨域
- 15.3.SpringBootAdmin界面化監控
- 第十六章 消息隊列的整合與使用
- 16.1.消息隊列與JMS規范簡介
- 16.2.使用docker安裝activeMQ
- 16.3.activeMQ實現點對點隊列
- 16.4.activeMQ實現發布訂閱隊列
- 16.5.docker安裝RocketMQ
- 16.6.RocketMQ實現2種消費模式
- WebFlux文檔遷移的說明
- 番外篇:周邊技術生態
- centos7安裝docker圖文詳解
- docker安裝mongodb(單點)圖文詳解
- 整合Spring data mongodb操作數據
- windows下如何安裝git
- springboot非web項目構建
- 多種方式shutdown應用服務
- SpringBoot-2.2版本的變化
- SpringBoot中如何使用Cookies
- 使用flyway管理數據庫版本
- SpringBoot解決跨域訪問的問題
- IDEA遠程調試linux上的SB項目
- 附錄一:mybatis-plus
- f1-1.CURD快速入門
- f1-2.條件構造器使用與總結
- f1-3.自定義SQL
- f1-4.表格分頁與下拉分頁查詢
- f1-5.ActiveRecord模式
- f1-6.主鍵生成策略
- f1-7.MybatisPlus代碼生成器
- f1-8.邏輯刪除
- f1-9.字段自動填充
- f1-10.多租戶解決方案
- f1-11 日志打印輸出
- 附錄二:RestTemplate
- f2-1.基本介紹及配置使用
- f2-2.底層HTTP客戶端庫的切換
- f2-3.GET請求使用詳解
- f2-4.POST請求使用詳解
- f2-5.HTTP method使用方法詳解
- f2-6.文件上傳與下載
- f2-7.請求失敗異常處理
- f2-8.自動重試機制
- f2-9.通過BasicAuth認證
- f2-10使用代理作為跳板