SpringBoot解決跨域的五種方式
在 Spring Boot 中解決跨域(CORS,Cross-Origin Resource Sharing)問題有 多種方式,適用于不同場景。下面系統(tǒng)地介紹 5 種主流方法,從簡單到靈活,附代碼示例和適用場景。
方法 1:使用 @CrossOrigin 注解(最簡單)
適用場景: 單個 Controller 或方法需要跨域
@RestController
@CrossOrigin(origins = "http://localhost:3000") // 允許指定來源
public class UserController {
@GetMapping("/user")
public User getUser() {
return new User("John");
}
// 或只對某個方法生效
@CrossOrigin(origins = "*") // 允許所有來源(生產(chǎn)環(huán)境慎用!)
@PostMapping("/save")
public String save() {
return "ok";
}
}
優(yōu)點:
- 簡單、直觀
- 可細(xì)粒度控制(類級別 or 方法級別)
缺點:
- 無法全局統(tǒng)一管理
- 不適合大型項目
方法 2:全局配置 CORS(推薦?。?/h2>
適用場景: 整個應(yīng)用統(tǒng)一處理跨域(最常用)
方式 A:實現(xiàn) WebMvcConfigurer 接口(Spring Boot 2.x+)
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 攔截所有路徑
.allowedOrigins("*")
// .allowedOrigins("http://localhost:3000", "https://your-app.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
// .allowCredentials(true) // 是否允許攜帶 cookie,?? 注意:這里不能同時設(shè)為 true!
.maxAge(3600); // 預(yù)檢請求緩存時間(秒)
}
}
方式 B:使用 @Bean 注冊 CorsConfigurationSource
@Configuration
public class CorsConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
// config.setAllowedOrigins(Arrays.asList("*")); // ?? 允許所有域
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowCredentials(true);
// config.setAllowCredentials(true); // ?? 不能與 "*" 同時使用!
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
優(yōu)點:
- 全局生效,配置集中
- 靈活控制路徑、方法、頭部等
- 生產(chǎn)環(huán)境推薦方式
方法 3:通過 Filter 自定義 CORS(底層控制)
適用場景: 需要完全自定義 CORS 響應(yīng)頭,或與 Spring Security 集成
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
// response.setHeader("Access-Control-Allow-Origin", "*");
// 注意:沒有 Allow-Credentials!
response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
// 如果是預(yù)檢請求(OPTIONS),直接返回
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
}
注意:如果使用 Spring Security,需確保此 Filter 在 Security Filter 之前執(zhí)行。
優(yōu)點:
- 完全控制響應(yīng)頭
- 可處理復(fù)雜邏輯(如動態(tài) origin)
缺點:
- 代碼較繁瑣
- 容易出錯(如漏掉 OPTIONS 處理)? 方法 4:在 application.yml / application.properties 中配置(僅限 Spring Boot 2.4+)
注意:Spring Boot 本身不支持通過配置文件直接開啟 CORS! 但如果你使用 Spring Cloud Gateway 或 某些 starter,可能有擴(kuò)展支持。
普通 Spring Boot Web 項目不能這樣配置!
所以:不要嘗試在 application.yml 里寫 cors 配置(除非你用的是特定網(wǎng)關(guān)組件)。
場景 1:Spring WebFlux(響應(yīng)式)項目
application.yml
spring:
webflux:
cors:
allowed-origins: "*"
allowed-methods: "GET,POST,PUT,DELETE,OPTIONS"
allowed-headers: "*"
max-age: 3600場景 2:Spring Boot Actuator 端點的 CORS 配置
即使你用的是 Spring MVC,Actuator 的監(jiān)控端點也支持通過配置文件開啟 CORS:
application.yml
management:
endpoints:
web:
cors:
allowed-origins: "http://localhost:3000"
allowed-methods: "*"
allowed-headers: "*"
| 項目類型 | 是否支持 application.yml 配置 CORS | 推薦方式 |
|---|---|---|
Spring MVC(spring-boot-starter-web) | ? 不支持 | 使用 WebMvcConfigurer 或 @CrossOrigin |
Spring WebFlux(spring-boot-starter-webflux) | ? 支持 | 用 spring.webflux.cors.* |
| Actuator 端點 | ? 支持(僅限監(jiān)控接口) | 用 management.endpoints.web.cors.* |
方法 4:結(jié)合 Spring Security 配置 CORS(安全場景必備)
如果你的項目用了 Spring Security,必須顯式啟用 CORS,否則 Security 會攔截 OPTIONS 請求!
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors().and() // ?? 關(guān)鍵:啟用 CORS 支持
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.anyRequest().permitAll()
);
return http.build();
}
// 同時提供全局 CorsConfigurationSource
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
為什么需要?
- Spring Security 默認(rèn)不處理 CORS
- 如果不配置,瀏覽器預(yù)檢請求(OPTIONS)會被 Security 攔截 → 跨域失敗
常見錯誤
| 問題 | 說明 |
|---|---|
allowedOrigins("*") + allowCredentials(true) 沖突 | 瀏覽器不允許:Access-Control-Allow-Origin 為 * 時,不能帶 cookie。必須指定具體 origin |
| 忘記處理 OPTIONS 請求 | 預(yù)檢請求失敗,導(dǎo)致跨域報錯 |
| CORS 配置被 Security 覆蓋 | 必須在 Spring Security 中顯式啟用 .cors(),否則 OPTIONS 請求會被攔截 |
生產(chǎn)環(huán)境使用 allowedOrigins("*") | 存在安全風(fēng)險,應(yīng)明確指定可信的前端域名 |
最佳實踐
| 場景 | 推薦方案 |
|---|---|
| 快速測試 / 小型項目 | 使用 @CrossOrigin 注解 |
| 標(biāo)準(zhǔn) Web 項目(未集成 Spring Security) | 實現(xiàn) WebMvcConfigurer 進(jìn)行全局 CORS 配置 |
| 項目已集成 Spring Security | 在 Security 配置中調(diào)用 .cors(),并提供 CorsConfigurationSource Bean |
| 需要動態(tài) Origin(如多租戶、白名單配置) | 自定義 CorsFilter 實現(xiàn)靈活控制 |
一句話記住:
普通項目用 WebMvcConfigurer,帶 Security 的項目必須在 Security 中 .cors() 并提供 CorsConfigurationSource。
以上就是SpringBoot解決跨域的五種方式的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot解決跨域的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Mybatis有查詢結(jié)果但存不進(jìn)實體類的解決方案
這篇文章主要介紹了Mybatis有查詢結(jié)果但存不進(jìn)實體類的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
Spring Boot 如何使用Liquibase 進(jìn)行數(shù)據(jù)庫遷移(操作方法)
在Spring Boot應(yīng)用程序中使用Liquibase進(jìn)行數(shù)據(jù)庫遷移是一種強(qiáng)大的方式來管理數(shù)據(jù)庫模式的變化,本文重點講解如何在Spring Boot應(yīng)用程序中使用Liquibase進(jìn)行數(shù)據(jù)庫遷移,從而更好地管理數(shù)據(jù)庫模式的變化,感興趣的朋友跟隨小編一起看看吧2023-09-09
java數(shù)據(jù)結(jié)構(gòu)實現(xiàn)雙向鏈表功能
這篇文章主要為大家詳細(xì)介紹了java數(shù)據(jù)結(jié)構(gòu)實現(xiàn)雙向鏈表功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11
解決因缺少Log4j依賴導(dǎo)致應(yīng)用啟動失敗的問題
日志是應(yīng)用軟件中不可缺少的部分,Apache的開源項目log4j是一個功能強(qiáng)大的日志組件,提供方便的日志記錄。但這篇文章不是介紹Log4j,這篇文章主要介紹了關(guān)于因缺少Log4j依賴導(dǎo)致應(yīng)用啟動失敗問題的相關(guān)資料,需要的朋友可以參考下。2017-04-04
springboot如何查找配置文件路徑的順序和其優(yōu)先級別
此文是在工作中遇到的關(guān)于springboot配置文件的問題,在網(wǎng)上查閱資料和自己測試之后記錄的,以便日后查閱。希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
Mybatis-Plus中的@TableName 和 table-prefix使用
table-prefix 是一個全局配置,它會自動在所有表名前添加指定的前綴,這個配置對于那些使用一致命名約定的數(shù)據(jù)庫表非常有用,這篇文章主要介紹了Mybatis-Plus中的@TableName 和 table-prefix使用,需要的朋友可以參考下2024-08-08

