SpringBoot處理跨域請求(CORS)的五種方式
一、CORS基礎(chǔ)概念
1. 什么是跨域請求?
當(dāng)瀏覽器從一個域名的網(wǎng)頁去請求另一個域名的資源時,如果域名、端口或協(xié)議不同,就會產(chǎn)生跨域請求。出于安全考慮,瀏覽器默認(rèn)會阻止這類請求。
2. 簡單請求 vs 預(yù)檢請求
類型 | 條件 | 處理方式 |
---|---|---|
簡單請求 | GET/HEAD/POST方法,且Content-Type為text/plain、multipart/form-data或application/x-www-form-urlencoded | 直接發(fā)送請求,帶Origin頭 |
預(yù)檢請求(OPTIONS) | 不符合簡單請求條件的其他請求 | 先發(fā)送OPTIONS請求,獲得許可后再發(fā)送實際請求 |
二、Spring Boot處理CORS的5種方式
1. 使用@CrossOrigin注解
適用場景:針對單個控制器或方法級別的CORS配置
@RestController @RequestMapping("/api") public class MyController { // 允許特定源的跨域訪問 @CrossOrigin(origins = "https://example.com") @GetMapping("/resource") public ResponseEntity<String> getResource() { return ResponseEntity.ok("跨域資源"); } // 更詳細(xì)的配置 @CrossOrigin(origins = {"https://example.com", "https://api.example.com"}, allowedHeaders = {"Content-Type", "Authorization"}, methods = {RequestMethod.GET, RequestMethod.POST}, maxAge = 3600) @PostMapping("/save") public ResponseEntity<String> saveResource() { return ResponseEntity.ok("保存成功"); } }
2. 全局CORS配置
適用場景:應(yīng)用級別的統(tǒng)一CORS配置
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") // 匹配的路徑 .allowedOrigins("https://example.com", "https://api.example.com") // 允許的源 .allowedMethods("GET", "POST", "PUT", "DELETE") // 允許的方法 .allowedHeaders("*") // 允許的請求頭 .exposedHeaders("Authorization", "Content-Disposition") // 暴露的響應(yīng)頭 .allowCredentials(true) // 是否允許發(fā)送cookie .maxAge(3600); // 預(yù)檢請求緩存時間(秒) // 可以添加多個配置 registry.addMapping("/public/**") .allowedOrigins("*"); } }
3. 使用Filter處理CORS
適用場景:需要更底層控制或與非Spring Web環(huán)境集成
@Configuration public class CorsFilterConfig { @Bean public FilterRegistrationBean<CorsFilter> corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); // 配置CORS規(guī)則 config.setAllowCredentials(true); config.addAllowedOrigin("https://example.com"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); config.setMaxAge(3600L); // 對所有路徑生效 source.registerCorsConfiguration("/**", config); FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source)); bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 設(shè)置最高優(yōu)先級 return bean; } }
4. Spring Security中的CORS配置
適用場景:使用Spring Security的項目
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and() // 啟用CORS支持 .csrf().disable() // 通常CORS和CSRF不能同時使用 .authorizeRequests() .antMatchers("/api/public/**").permitAll() .anyRequest().authenticated(); } // 提供CORS配置源 @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("https://example.com")); configuration.setAllowedMethods(Arrays.asList("GET", "POST")); configuration.setAllowedHeaders(Arrays.asList("*")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
5. 響應(yīng)頭手動設(shè)置
適用場景:需要動態(tài)控制CORS頭
@RestController public class DynamicCorsController { @GetMapping("/dynamic-cors") public ResponseEntity<String> dynamicCors(HttpServletRequest request, HttpServletResponse response) { // 根據(jù)請求動態(tài)設(shè)置CORS頭 String origin = request.getHeader("Origin"); if (isAllowedOrigin(origin)) { response.setHeader("Access-Control-Allow-Origin", origin); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "GET, POST"); } return ResponseEntity.ok("動態(tài)CORS響應(yīng)"); } private boolean isAllowedOrigin(String origin) { // 實現(xiàn)你的源驗證邏輯 return origin != null && origin.endsWith("example.com"); } }
三、CORS配置詳解
1. 核心響應(yīng)頭說明
響應(yīng)頭 | 說明 |
---|---|
Access-Control-Allow-Origin | 允許訪問的源,可以是具體域名或*(不推薦使用*,特別是需要憑證時) |
Access-Control-Allow-Methods | 允許的HTTP方法(GET, POST等) |
Access-Control-Allow-Headers | 允許的請求頭 |
Access-Control-Expose-Headers | 瀏覽器可以訪問的響應(yīng)頭 |
Access-Control-Allow-Credentials | 是否允許發(fā)送cookie(true/false),設(shè)為true時Allow-Origin不能為* |
Access-Control-Max-Age | 預(yù)檢請求結(jié)果的緩存時間(秒) |
2. 常見問題解決方案
問題1:預(yù)檢請求(OPTIONS)被攔截
解決方案:
- 確保OPTIONS請求不被安全框架攔截
- 在Spring Security中配置:
http.cors().and() .authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
問題2:帶憑證的請求失敗
解決方案:
- 確保
allowCredentials(true)
和具體的allowedOrigins
(不能是*) - 前端需要設(shè)置
withCredentials: true
(如axios)
問題3:特定響應(yīng)頭無法獲取
解決方案:
- 使用
exposedHeaders
暴露需要的頭:
.exposedHeaders("Custom-Header", "Authorization")
四、最佳實踐建議
- 生產(chǎn)環(huán)境不要使用通配符*:明確指定允許的源
- 合理限制HTTP方法:只開放必要的方法(GET/POST等)
- 考慮使用環(huán)境變量:動態(tài)配置允許的源
@Value("${cors.allowed.origins}") private String[] allowedOrigins; // 在配置中使用 .allowedOrigins(allowedOrigins)
- 結(jié)合安全框架:Spring Security項目使用專門的CORS配置
- 測試不同場景:簡單請求和預(yù)檢請求都要測試
五、完整配置示例
@Configuration @EnableWebMvc public class CorsConfig implements WebMvcConfigurer { @Value("${app.cors.allowed-origins}") private String[] allowedOrigins; @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins(allowedOrigins) .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") .allowedHeaders("*") .exposedHeaders("Authorization", "Content-Disposition") .allowCredentials(true) .maxAge(3600); registry.addMapping("/public/**") .allowedOrigins("*") .allowedMethods("GET", "OPTIONS"); } // 可選:提供CORS過濾器作為備選 @Bean public FilterRegistrationBean<CorsFilter> corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.applyPermitDefaultValues(); config.setAllowCredentials(true); config.setAllowedOrigins(Arrays.asList(allowedOrigins)); source.registerCorsConfiguration("/**", config); FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source)); bean.setOrder(Ordered.HIGHEST_PRECEDENCE); return bean; } }
六、總結(jié)
Spring Boot提供了多種靈活的方式來處理CORS:
- 簡單場景:使用
@CrossOrigin
注解 - 統(tǒng)一配置:實現(xiàn)
WebMvcConfigurer
的addCorsMappings
方法 - 底層控制:配置
CorsFilter
- 安全項目:結(jié)合Spring Security的
cors()
配置 - 動態(tài)需求:手動設(shè)置響應(yīng)頭
根據(jù)項目需求選擇合適的方式,并遵循安全最佳實踐,可以有效地解決跨域問題,同時保證應(yīng)用的安全性。
以上就是SpringBoot處理跨域請求(CORS)的五種方式的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot處理跨域請求的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringMVC + servlet3.0 文件上傳的配置和實現(xiàn)代碼
本篇文章主要介紹了SpringMVC + servlet3.0 文件上傳的配置和實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04mybatis 如何利用resultMap復(fù)雜類型list映射
這篇文章主要介紹了mybatis 如何利用resultMap復(fù)雜類型list映射的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07RocketMQ?NameServer架構(gòu)設(shè)計啟動流程
這篇文章主要為大家介紹了RocketMQ?NameServer架構(gòu)設(shè)計啟動流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02java實現(xiàn)酷狗音樂臨時緩存文件轉(zhuǎn)換為MP3文件的方法
這篇文章主要介紹了java實現(xiàn)酷狗音樂臨時緩存文件轉(zhuǎn)換為MP3文件的方法,涉及java針對文件操作的相關(guān)技巧,需要的朋友可以參考下2016-08-08Java實現(xiàn)Jar文件的遍歷復(fù)制與文件追加
這篇文章主要為大家詳細(xì)介紹了如何利用Java實現(xiàn)Jar文件的遍歷復(fù)制與文件追加功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-11-11