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

Spring Security 5.7无WebSecurityConfigurerAdapter多认证提供者异常排查

问题分析与解决方案

一、仅DaoAuthenticationProvider生效,LdapAuthProvider未被调用的原因及解决

核心原因

Spring Security的AuthenticationManager会按Provider添加顺序依次调用认证提供者:

  1. 若某个Provider成功完成认证,直接返回结果;
  2. 若某个Provider抛出AuthenticationException(如密码错误、用户不存在),流程会直接终止,不会继续调用后续Provider;
  3. 仅当Provider返回null(表示无法处理当前认证请求)时,才会尝试下一个Provider。

你的场景中,DaoAuthenticationProvider在验证失败时(无论用户是否存在、密码是否正确)都会抛出对应异常,而非返回null,导致LdapAuthProvider完全没有被触发的机会。而移除DaoProvider后,LdapProvider自然成为唯一的选择,因此可以正常工作。

解决方法

自定义DaoAuthenticationProvider,重写authenticate方法,在验证失败时返回null,让AuthenticationManager继续尝试下一个Provider:

public class CustomDaoAuthenticationProvider extends DaoAuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            // 尝试正常认证
            return super.authenticate(authentication);
        } catch (AuthenticationException e) {
            // 认证失败时返回null,交由下一个Provider处理
            return null;
        }
    }
}

然后替换原有的authenticationProvider Bean定义:

@Bean
public DaoAuthenticationProvider authenticationProvider() {
    CustomDaoAuthenticationProvider authProvider = new CustomDaoAuthenticationProvider();
    authProvider.setUserDetailsService(userService);
    authProvider.setPasswordEncoder(passwordEncoder());
    return authProvider;
}

同时保持Provider的添加顺序(你当前代码中先添加Ldap再添加Dao的顺序是合理的,若想优先尝试Dao,可调换顺序)。


二、全局AuthenticationManager未包含自定义Provider的原因及解决

核心原因

你通过AuthenticationConfiguration.getAuthenticationManager()获取的是Spring Security默认的全局AuthenticationManager,而你添加的Provider仅注册到了SecurityFilterChain对应的局部AuthenticationManager中,全局实例并未包含这些自定义Provider。

解决方法

手动构建全局AuthenticationManager,将两个自定义Provider注册进去:

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
    AuthenticationManagerBuilder�man<span// Kaphus支持默认 decorated
其他 Stop处 POJO的,哦不对,正确代码:
    AuthenticationManagerBuilder authBuilder = authConfig.getAuthenticationManagerBuilder();
    // 注册Ldap认证提供者
    authBuilder.authenticationProvider(ldapAuthProvider);
    // 注册自定义Dao认证提供者
    authBuilder.authenticationProvider(authenticationProvider());
    return authBuilder.build();
}

此时,你通过@Autowired注入的AuthenticationManager就会包含两个自定义Provider,调用authenticate方法时会按注册顺序依次尝试认证。

可选优化

如果你希望SecurityFilterChain也使用这个全局的AuthenticationManager,可以在securityFilterChain方法中指定,避免重复添加Provider:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
    http
            .cors()
            .and().csrf().disable()
            .headers().frameOptions().disable()
            .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and().authorizeRequests()
                .antMatchers("/api/test/**", "/auth/**", "/h2-console/**").permitAll()
                .anyRequest().authenticated()
            .and().addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
            // 指定使用全局AuthenticationManager
            .authenticationManager(authenticationManager);
    return http.build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 04:03:04