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

Spring Security:捕获Active Directory错误凭证的LDAP认证异常

Spring Boot集成Active Directory认证时错误凭证引发栈溢出问题

我正在用Spring Boot和Active Directory构建认证过滤器,当前配置代码如下:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    private static final String DOMAIN = "xxxxx.net";
    private static final String URL = "ldap://xxxxxx:389/";

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(AbstractHttpConfigurer::disable)
                .cors(cors -> cors
                        .configurationSource(request -> {
                            CorsConfiguration corsConfiguration = new CorsConfiguration();
                            corsConfiguration.setAllowedOrigins(List.of("http://localhost:4200"));
                            corsConfiguration.setAllowedMethods(List.of("POST", "PUT", "GET", "DELETE", "OPTIONS"));
                            corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
                            corsConfiguration.setAllowCredentials(true);
                            return corsConfiguration;
                        }))
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("auth/**").permitAll()
                        .anyRequest().authenticated())
                .formLogin(login -> login.permitAll())
        .sessionManagement(session ->
                        session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));
        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder auth = http.getSharedObject(AuthenticationManagerBuilder.class);

        ActiveDirectoryLdapAuthenticationProvider adProvider =
                new ActiveDirectoryLdapAuthenticationProvider(DOMAIN, URL);
        adProvider.setConvertSubErrorCodesToExceptions(true);
        adProvider.setUseAuthenticationRequestCredentials(true);

        auth.authenticationProvider(adProvider);

        return auth.build();
    }
}

使用Spring Security默认登录表单提交正确凭证时功能正常,但提交错误凭证时,控制台会出现无限循环的异常日志:

2024-06-22T01:56:14.121-05:00 DEBUG 19756 --- [waza] [nio-8080-exec-4] ctiveDirectoryLdapAuthenticationProvider : Authentication for fr@xxxxx.net failed:javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090439, comment: AcceptSecurityContext error, data 52e, v4563 ]
2024-06-22T01:56:14.123-05:00  INFO 19756 --- [waza] [nio-8080-exec-4] ctiveDirectoryLdapAuthenticationProvider : Active Directory authentication failed: Supplied password was invalid
2024-06-22T01:56:14.136-05:00 DEBUG 19756 --- [waza] [nio-8080-exec-4] ctiveDirectoryLdapAuthenticationProvider : Authentication for fr@xxxxxx.net failed:javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090439, comment: AcceptSecurityContext error, data 52e, v4563 ]
2024-06-22T01:56:14.136-05:00  INFO 19756 --- [waza] [nio-8080-exec-4] ctiveDirectoryLdapAuthenticationProvider : Active Directory authentication failed: Supplied password was invalid

最终会触发栈溢出错误:

2024-06-22T01:56:19.888-05:00 ERROR 19756 --- [waza] [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Filter execution threw an exception] with root cause

java.lang.StackOverflowError: null
    at java.base/java.net.URI$Parser.scan(URI.java:3141) ~[na:na]

如何捕获该LDAP认证异常,防止栈溢出或终止错误操作?


解决方案

修改配置代码,将ActiveDirectoryLdapAuthenticationProvider单独提取为Bean,同时移除默认表单登录的permitAll()配置(这是触发无限循环的核心原因),修改后的代码如下:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    private static final String DOMAIN = "xxxxx.net";
    private static final String URL = "ldap://xxxxxx:389/";

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable())
        .cors(cors -> cors.configurationSource(request -> {
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            corsConfiguration.setAllowedOrigins(List.of("http://localhost:4200"));
            corsConfiguration.setAllowedMethods(List.of("POST", "PUT", "GET", "DELETE", "OPTIONS"));
            corsConfiguration.setAllowedHeaders(List.of("Authorization", "Content-Type"));
            corsConfiguration.setAllowCredentials(true);
            return corsConfiguration;
        }))
        .authorizeHttpRequests(
                authorize -> authorize.requestMatchers("auth/**").permitAll()
            .anyRequest().authenticated())
                .sessionManagement(session -> 
                    session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));
        return http.build();
    }

    @Bean
    AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder auth = http.getSharedObject(AuthenticationManagerBuilder.class);
        ActiveDirectoryLdapAuthenticationProvider adProvider = authProvider();
        auth.authenticationProvider(adProvider);
        return auth.build();
    }

    @Bean
    ActiveDirectoryLdapAuthenticationProvider authProvider() {
        ActiveDirectoryLdapAuthenticationProvider adlap = new ActiveDirectoryLdapAuthenticationProvider(DOMAIN, URL);
        adlap.setUseAuthenticationRequestCredentials(true);
        adlap.setConvertSubErrorCodesToExceptions(true);
        return adlap;
    }
}

说明:移除formLogin(login -> login.permitAll())后,Spring Security会正确处理认证失败流程,避免无限循环;将认证提供者单独声明为Bean,确保其被Spring容器正确初始化和管理,从而正常捕获LDAP认证异常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:18:12