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

使用@Component自定义认证提供者致BasicAuthenticationFilter异常

问题原因分析

你遇到的ProviderNotFoundException本质原因是:

  • 启用HttpBasic认证后,BasicAuthenticationFilter会从请求头的Basic信息生成UsernamePasswordAuthenticationToken,并提交给认证管理器处理。
  • 但你的CustomAuthenticationProvider仅声明支持CustomAuthentication类型,且Spring Security认证管理器中没有其他能处理UsernamePasswordAuthenticationToken的提供者,导致无法匹配到合适的认证逻辑。

另外,当你用@Component注册自定义认证提供者后,Spring Security会自动将其加入认证管理器的提供者列表,但默认的DaoAuthenticationProvider(负责处理UsernamePasswordAuthenticationToken)不会被自动注册,除非你配置了UserDetailsService且没有手动干预认证管理器的构建。

解决方案

根据你的业务需求,有两种处理方式:

方式1:让自定义认证提供者同时支持两种Token类型

如果你的业务允许同一个提供者处理Basic认证和自定义认证,可以修改CustomAuthenticationProvider的supports方法,同时兼容两种Token类型:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
    @Override
    public boolean supports(Class<?> authentication) {
        // 同时支持自定义认证Token和Basic认证的UsernamePasswordAuthenticationToken
        return CustomAuthentication.class.isAssignableFrom(authentication)
                || UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 分支处理不同类型的Token
        if (authentication instanceof CustomAuthentication) {
            // 自定义认证逻辑
        } else if (authentication instanceof UsernamePasswordAuthenticationToken) {
            // Basic认证逻辑:验证用户名密码,比如调用UserDetailsService
        }
        // 抛出认证异常或返回认证成功的Authentication对象
    }
}

方式2:在认证管理器中同时注册两个提供者

如果希望分开处理两种认证逻辑,保持自定义提供者的独立性,可以在Security配置中手动构建认证管理器,同时加入自定义提供者和支持Basic认证的默认提供者:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    private final UserDetailsService userDetailsService;
    private final CustomAuthenticationProvider customAuthenticationProvider;

    // 构造注入依赖
    public WebSecurityConfig(UserDetailsService userDetailsService,
                             CustomAuthenticationProvider customAuthenticationProvider) {
        this.userDetailsService = userDetailsService;
        this.customAuthenticationProvider = customAuthenticationProvider;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .httpBasic(Customizer.withDefaults())
                .addFilterBefore(customFilter, BasicAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        AuthenticationManagerBuilder builder = authConfig.getAuthenticationManagerBuilder();
        // 添加自定义认证提供者
        builder.authenticationProvider(customAuthenticationProvider);
        // 添加支持UsernamePasswordAuthenticationToken的DaoAuthenticationProvider
        DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
        daoProvider.setUserDetailsService(userDetailsService);
        // 配置密码编码器(如果你的用户密码是加密存储的)
        // daoProvider.setPasswordEncoder(passwordEncoder());
        builder.authenticationProvider(daoProvider);
        return builder.build();
    }

    // 可选:如果需要密码编码器,添加该Bean
    // @Bean
    // public PasswordEncoder passwordEncoder() {
    //     return new BCryptPasswordEncoder();
    // }
}

额外说明

如果你的业务场景不需要Basic认证,仅需自定义认证,那么直接移除配置中的.httpBasic(Customizer.withDefaults())即可,这样就不会触发UsernamePasswordAuthenticationToken的认证流程,也就不会出现这个异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 06:37:24