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

Spring Boot 3.2.1下如何同时使用Spring Security自定义认证提供者与默认认证提供者

Spring Boot 3.2.1下如何同时使用Spring Security自定义认证提供者与默认认证提供者

我来帮你解决这个问题!你的核心需求是先通过请求头(X-CLIENT-ID、X-API-KEY)完成认证,失败后自动回退到Basic认证,但目前默认的Basic认证提供者没有被加入到认证管理器中,导致回退逻辑无法生效。

问题原因分析

当你手动调用authenticationManagerBuilder.authenticationProvider()添加自定义认证提供者时,Spring Security会认为你想要完全控制认证提供者的列表,因此不会自动注入默认的提供者(比如用于Basic认证的DaoAuthenticationProvider)。这就是你在debug中只看到自定义RequestHeaderAuthenticationProvider和匿名提供者的原因。

解决方案:显式包含默认认证提供者

要同时使用自定义和默认提供者,你需要在配置中显式把默认的DaoAuthenticationProvider(对应Basic认证)加入到认证管理器中,最便捷的方式是通过关联UserDetailsService来触发默认提供者的自动创建,同时还要注意密码编码器的配置(Spring Security 3.x强制要求密码加密)。

步骤1:添加密码编码器Bean

@Bean
PasswordEncoder passwordEncoder() {
    // 测试环境可以用NoOp,生产环境请替换为BCryptPasswordEncoder等安全编码器
    return NoOpPasswordEncoder.getInstance();
}

步骤2:修改SecurityConfiguration配置

调整认证管理器的构建逻辑,同时添加自定义提供者和默认的UserDetailsService关联:

@Configuration
public class SecurityConfiguration {

    private static final String CLIENT_ID_HEADER_NAME = "X-CLIENT-ID";
    private static final String API_KEY_HEADER_NAME = "X-API-KEY";

    private final RequestHeaderAuthenticationProvider authenticationProvider;

    public SecurityConfiguration(RequestHeaderAuthenticationProvider authenticationProvider) {
        this.authenticationProvider = authenticationProvider;
    }

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        
        // 1. 添加自定义认证提供者
        authenticationManagerBuilder.authenticationProvider(this.authenticationProvider);
        // 2. 关联UserDetailsService,触发默认DaoAuthenticationProvider的创建(用于Basic认证)
        authenticationManagerBuilder.userDetailsService(inMemoryUserDetailsManager(passwordEncoder()))
                                    .passwordEncoder(passwordEncoder());

        http.csrf(CsrfConfigurer::disable)
            .cors(CorsConfigurer::disable)
            .formLogin(FormLoginConfigurer::disable)
            .httpBasic(Customizer.withDefaults());

        http.authorizeHttpRequests(request -> request.anyRequest().authenticated());

        // 关键:把自定义过滤器放在BasicAuthenticationFilter之前,保证优先执行请求头认证
        http.addFilterBefore(requestHeaderAuthenticationFilter(http), BasicAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter(HttpSecurity http) throws Exception {
        RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
        filter.setPrincipalRequestHeader(CLIENT_ID_HEADER_NAME);
        filter.setCredentialsRequestHeader(API_KEY_HEADER_NAME);
        filter.setExceptionIfHeaderMissing(false);
        filter.setAuthenticationManager(authenticationManager(http));
        return filter;
    }

    @Bean
    AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        return authenticationManagerBuilder.build();
    }

    @Bean
    InMemoryUserDetailsManager inMemoryUserDetailsManager(PasswordEncoder passwordEncoder) {
        UserDetails admin = User.withUsername("admin")
                                .password(passwordEncoder.encode("admin"))
                                .roles("USER")
                                .build();
        return new InMemoryUserDetailsManager(admin);
    }
}

步骤3:验证逻辑

修改完成后,ProviderManager的提供者列表会包含:

  • RequestHeaderAuthenticationProvider(优先执行)
  • DaoAuthenticationProvider(Basic认证用)
  • AnonymousAuthenticationProvider

此时请求会先尝试请求头认证,失败后自动触发Basic认证,完全符合你的需求。

对你疑问的解答

Spring Security是否在注册自定义Provider为Bean时自动排除默认Provider?

是的。当你手动通过AuthenticationManagerBuilder添加认证提供者时,Spring Security会关闭默认提供者的自动注入逻辑,因为它认为你想要完全掌控认证流程。因此必须显式添加所有需要的提供者,包括默认的那些。

备注:内容来源于stack exchange,提问作者koreanDev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 10:24:52