Spring Boot:LDAP 错误:错误代码 49 - 80090308:LdapErr:DSID-0C090439,注释:AcceptSecurityContext 错误,数据 52e

Spring Boot: LDAP Error: error code 49 - 80090308: LdapErr: DSID-0C090439, comment: AcceptSecurityContext error, data 52e

提问人:Sascha Heimann 提问时间:3/27/2023 更新时间:10/20/2023 访问量:1553

问:

我有一个Spring Boot Web应用程序,它像魅力一样使用dao身份验证。但我也想实现 Active Directory 身份验证。

出于测试目的,我修改了我的 SecurityConfig:

package com.sheimann.demoapp.config;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import org.springframework.security.web.SecurityFilterChain;

import com.sheimann.demoapp.service.UserServiceImpl;


/**
 * The Class WebSecurityConfig.
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    /** The success handler. */
    @Autowired
    private CustomLoginSucessHandler sucessHandler;
    
    @Autowired
    private CustomLoginFailureHandler failureHandler;

    /**
     * User details service.
     *
     * @return the user details service
     */
    @Bean
    UserDetailsService userDetailsService() {
        return new UserServiceImpl();
    }

    /**
     * Password encoder.
     *
     * @return the b crypt password encoder
     */
    @Bean
    BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * Authentication provider.
     *
     * @return the dao authentication provider
     */
    @Bean
    DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService());
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

    @Bean
    public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
    
        ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider = 
        new ActiveDirectoryLdapAuthenticationProvider( "mydomainName.com", "ldap://mydcipaddress:389", "dc=my,dc=domain,dc=com");
    
        // to parse AD failed credentails error message due to account - expiry,lock, credentialis - expiry,lock
        activeDirectoryLdapAuthenticationProvider.setConvertSubErrorCodesToExceptions(true); 
        activeDirectoryLdapAuthenticationProvider.setUseAuthenticationRequestCredentials(true);
        activeDirectoryLdapAuthenticationProvider.setSearchFilter("(&(objectClass=user)(sAMAccountName={0}))");
        
        return activeDirectoryLdapAuthenticationProvider;
    }


    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return new ProviderManager(List.of(activeDirectoryLdapAuthenticationProvider()));
    }
 
    /**
     * Filter chain.
     *
     * @param http the http
     * @return the security filter chain
     * @throws Exception the exception
     */
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests()
                // URL matching for accessibility
                .requestMatchers("/datatables/**",
                        "/css/**",
                        "/js/**",
                        "/webjars/**",
                        "/app.js",
                        "/app.css",
                        "/just-validate/**",
                        "/bootstrap-icons/**",
                        "/bootstrap/**",
                        "/popperjs/**",
                        "/select2-bootstrap-5-theme-1.3.0/**",
                        "/select2-4.1.0-rc.0/**",
                        "/jquery/**",
                        "/*.p12",
                        "/login",
                        "/register",
                        "/resetPw1",
                        "/resetPw2",
                        "/error",
                        "/logout",
                        "/images/**")
                .permitAll()
                .requestMatchers("/admin/**").hasAnyAuthority("ADMIN")
                .requestMatchers("/user/**").authenticated()
                .anyRequest().authenticated()
                .and()                
                // form login
                .csrf((csrf) -> csrf.disable())
                .formLogin(login -> login
                        .loginPage("/login")
                        .failureHandler(failureHandler)
                        .successHandler(sucessHandler)
                        .usernameParameter("email")
                        .passwordParameter("password"))
                // logout
                .logout(logout -> logout
                        .logoutSuccessUrl("/login?res=logoutSuccess"))
                .exceptionHandling(handling -> handling
                        .accessDeniedPage("/access-denied"))
                .authenticationManager(authenticationManager());
                
        // session
        /*
         * .and()
         * .sessionManagement()
         * .invalidSessionUrl("/login?res=sst");
         */
        //http.authenticationProvider(authenticationProvider());
        http.headers(headers -> headers.frameOptions().sameOrigin());
        return http.build();
    } 

}

看起来,由于添加了 activeDirectoryLdapAuthenticationProvider 并将 AuthenticationManager 设置为仅使用 activeDirectoryLdapAuthenticationProvider 作为提供程序,我的应用程序正在使用此提供程序。

Wehn 我尝试登录,我的应用程序抛出以下错误:

Caused by: javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090439, comment: AcceptSecurityContext error, data 52e, v4563]

由于我已经搜索了整个互联网(感觉是这样),我知道 52e 的意思是:找到用户名但密码无效/错误。

问题是,这不是事实!我已经在几个ldap / active directory客户端上测试了我的帐户,并且该帐户可以100%工作!

希望有人能在这里让我朝着正确的方向前进......

非常感谢,祝您编码愉快...

萨沙

java spring-boot active-directory spring-security-ldap

评论

0赞 Michael Manley 10/17/2023
有运气找到任何答案吗?我知道有人遇到过类似的事情......

答:

-1赞 mrnst 10/20/2023 #1

最近,我们的一个Spring Boot应用程序收到了相同的错误消息,该应用程序以非常相似的设置连接到AD。该错误仅发生在一个特殊用户身上,并且密码正确。

我们观察到该问题是由密码中的特殊字符(德语“变音符号”)引起的。更改密码并删除变音符号解决了该问题。