You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何排除Spring Boot Security内部私有配置类OAuth2SecurityFilterChainConfiguration

如何排除Spring Boot OAuth2资源服务器的自动配置内部类

问题背景

我有一个实现基础认证和OAuth2认证的外部库,其中定义了基础认证的SecurityFilterChain:

@Bean
@ConditionalOnMissingBean
public AuthorizeRequestsCustomizer authorizeRequestsCustomizer(
    @Qualifier("basicAndFormMvc") MvcRequestMatcher.Builder mvc) {
  return customizer ->
      customizer.requestMatchers(mvc.pattern("/api/**")).authenticated().anyRequest().permitAll();
}

@Order(3)
@Bean("basicAndFormAuthFilter")
public SecurityFilterChain filterChain(
    HttpSecurity http, AuthorizeRequestsCustomizer authorizeRequestsCustomizer) throws Exception {

  http.sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
      .csrf(AbstractHttpConfigurer::disable)
      .cors(withDefaults())
      .httpBasic(withDefaults())
      .formLogin(withDefaults())
      .exceptionHandling(
          c ->
              c.defaultAuthenticationEntryPointFor(
                  customAuthenticationEntryPoint(), new AntPathRequestMatcher("/**")))
      .authorizeHttpRequests(authorizeRequestsCustomizer);

  return http.build();
}

启动时出现冲突错误:

[                  main] [ERROR] o.springframework.boot.SpringApplication: [] Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain': Cannot create inner bean '(inner bean)#7f088b5c' while setting constructor argument with key [1]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBeanValue(BeanDefinitionValueResolver.java:421)
    ...(省略中间栈信息)
Caused by: java.lang.IllegalArgumentException: A filter chain that matches any request [DefaultSecurityFilterChain defined as 'basicAndFormAuthFilter' in [class path resource [/BasicAndFormAuthConfig.class]] matching [any request] and having filters [DisableEncodeUrl, WebAsyncManagerIntegration, SecurityContextHolder, HeaderWriter, Cors, Logout, UsernamePasswordAuthentication, DefaultResources, DefaultLoginPageGenerating, DefaultLogoutPageGenerating, BasicAuthentication, RequestCacheAware, SecurityContextHolderAwareRequest, AnonymousAuthentication, SessionManagement, ExceptionTranslation]] has already been configured, which means that this filter chain [DefaultSecurityFilterChain defined as 'jwtSecurityFilterChain' in [class path resource [org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerJwtConfiguration$OAuth2SecurityFilterChainConfiguration.class]] matching [any request] and having filters [DisableEncodeUrl, WebAsyncManagerIntegration, SecurityContextHolder, HeaderWriter, Csrf, Logout, BearerTokenAuthentication, RequestCacheAware, SecurityContextHolderAwareRequest, AnonymousAuthentication, ExceptionTranslation, Authorization]] will never get invoked. Please use `HttpSecurity#securityMatcher` to ensure that there is only one filter chain configured for 'any request' and that the 'any request' filter chain is published last.
    at org.springframework.security.config.annotation.web.builders.WebSecurity.performBuild(WebSecurity.java:320)
    ...(省略末尾栈信息)

错误根源是外部库中OAuth2ResourceServerJwtConfiguration的内部类OAuth2SecurityFilterChainConfiguration定义的SecurityFilterChain(bean名jwtSecurityFilterChain):

@Configuration(proxyBeanMethods = false)
    @ConditionalOnDefaultWebSecurity
    static class OAuth2SecurityFilterChainConfiguration {

        @Bean
        @ConditionalOnBean(JwtDecoder.class)
        SecurityFilterChain jwtSecurityFilterChain(HttpSecurity http) throws Exception {
            http.authorizeHttpRequests((requests) ->
                requests.anyRequest().authenticated());
            http.oauth2ResourceServer((resourceServer) ->
                resourceServer.jwt(withDefaults()));
            return http.build();
        }

    }

由于该配置类属于外部库无法直接修改,且常规禁用Spring Security自动配置的方案无效,需要在无@SpringBootApplication注解的自定义本地库中排除这个包私有内部配置类。

解决方案

方法1:通过@ComponentScan排除内部配置类

在自定义库的核心配置类上,利用@ComponentScan的excludeFilters指定排除目标内部类(注意内部类全类名用$连接外部类与内部类):

@Configuration
@ComponentScan(
    excludeFilters = {
        @ComponentScan.Filter(
            type = FilterType.ASSIGNABLE_TYPE,
            value = org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerJwtConfiguration.OAuth2SecurityFilterChainConfiguration.class
        )
    }
)
public class CustomSecurityConfig {
    // 自定义配置逻辑
}

方法2:实现BeanDefinitionRegistryPostProcessor手动移除Bean定义

通过Spring扩展点,在Bean定义注册阶段直接移除目标配置类和对应的FilterChain Bean:

@Configuration
public class RemoveJwtFilterChainConfig implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 内部类的Bean名称格式:外部类全类名.$内部类名
        String configBeanName = "org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerJwtConfiguration$OAuth2SecurityFilterChainConfiguration";
        if (registry.containsBeanDefinition(configBeanName)) {
            registry.removeBeanDefinition(configBeanName);
        }
        // 移除对应的jwtSecurityFilterChain Bean
        String filterChainBeanName = "jwtSecurityFilterChain";
        if (registry.containsBeanDefinition(filterChainBeanName)) {
            registry.removeBeanDefinition(filterChainBeanName);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 无需额外操作
    }
}

方法3:利用条件注解阻止自动配置生效

目标配置类带有@ConditionalOnDefaultWebSecurity注解,该注解会检查是否存在特定标记Bean。在自定义库中添加同名标记Bean,即可让原条件失效:

@Configuration
public class DisableDefaultWebSecurityConfig {
    @Bean
    public DefaultWebSecurityMarker disableDefaultWebSecurityMarker() {
        return new DefaultWebSecurityMarker();
    }

    // 自定义标记类,无需实现任何方法
    public static class DefaultWebSecurityMarker {}
}

内容的提问来源于stack exchange,提问作者wuttke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:20:55