Spring Boot自动配置中CorsConfigurationSource未生效的问题排查
问题原因
自动配置的CorsConfigurationSource未生效的核心原因是:
Spring Boot WebMvc模块的自动配置会默认创建一个名为mvcHandlerMappingIntrospector的Bean,该Bean实现了CorsConfigurationSource接口。你的自动配置类中@ConditionalOnMissingBean的默认逻辑会扫描所有该类型的Bean,这个默认Bean的存在直接导致条件不满足,因此自动配置的Bean不会被创建。
从自动配置报告也能明确看到这一点:
WebMvcSecurityAutoConfiguration#corsConfigurationSource:
Did not match:
- @ConditionalOnMissingBean (types: org.springframework.web.cors.CorsConfigurationSource; SearchStrategy: all) found beans of type 'org.springframework.web.cors.CorsConfigurationSource' mvcHandlerMappingIntrospector (OnBeanCondition)
解决方案
修改自动配置中corsConfigurationSource Bean的@ConditionalOnMissingBean注解,添加ignoredBeans参数排除Spring默认的mvcHandlerMappingIntrospector Bean,让条件仅检查用户自定义的CorsConfigurationSource Bean:
@Bean @ConditionalOnMissingBean(value = CorsConfigurationSource.class, ignoredBeans = "mvcHandlerMappingIntrospector") CorsConfigurationSource corsConfigurationSource(WebMvcSecurityProperties properties) { // 原Bean实现逻辑保持不变 CorsConfiguration configuration = new CorsConfiguration(); Cors cors = properties.cors(); configuration.setAllowedOrigins(cors.origins()); configuration.setAllowedHeaders( cors.allowedHeaders() != null ? cors.allowedHeaders() : List.of(CorsConfiguration.ALL)); configuration.setAllowedMethods( cors.allowedMethods() != null ? cors.allowedMethods() : List.of(CorsConfiguration.ALL)); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }
效果验证
- 当应用未自定义
CorsConfigurationSourceBean时,自动配置的Bean会正常创建,并被注入到SecurityFilterChain中生效; - 当应用自定义了
CorsConfigurationSourceBean时,自动配置的Bean会被跳过,优先使用用户自定义的Bean,完全符合需求。
补充说明
添加@Order(HIGHEST_PRECEDENCE)无效的原因:@Order仅控制自动配置类的加载顺序,但mvcHandlerMappingIntrospector是WebMvc自动配置提前创建的Bean,即使你的配置类优先级更高,容器中已经存在该类型Bean,@ConditionalOnMissingBean条件依然不满足,因此无法解决问题。
内容的提问来源于stack exchange,提问作者Wim Deblauwe

