Spring Security Active Directory LDAP 身份验证错误

Posted

技术标签:

【中文标题】Spring Security Active Directory LDAP 身份验证错误【英文标题】:Spring Security Active directory LDAP Authentication error 【发布时间】:2020-04-08 01:46:38 【问题描述】:

当我使用 Spring Security Active directory LDAP 身份验证时,当用户通过身份验证时,我收到一条错误消息 PartialResultException。我还创建了一个测试运行程序文件,它在其中对用户进行身份验证而没有错误,但是在针对活动目录进行身份验证时,我无法进行身份验证。感谢您的宝贵帮助。

Test Runner2.java 文件

package com.company.test;

import java.util.Hashtable;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;


public class Runner2 

    private static String providerUrl = "ldap://ADHO.COMPANY.NET:389";

    private static String principle = "@company.ad";

    public static final String SEARCH_BY_SAM_ACCOUNT_NAME = "(sAMAccountName=%s)";

    public static boolean authenticateAD(String user , String password) throws Exception 

        InitialDirContext context=null;
        Hashtable<String, String> env = new Hashtable<String, String>();
        String securityPrinciple = user + principle;
        System.out.println("Security principal to search ->"+securityPrinciple);

        // Configure our directory context environment.
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, providerUrl);
        env.put(Context.SECURITY_PRINCIPAL, securityPrinciple);
        env.put(Context.SECURITY_CREDENTIALS, password);
        try 

        context = new InitialDirContext(env);       
        return true;

        catch(AuthenticationException e) 

         throw new AuthenticationException();

        catch(Exception e) 

            throw new Exception();
        
        finally  
            try 
                if (context != null) 
                    context.close();
                
             catch (NamingException e) 

             
         

    

    public static void main(String[] args) throws Exception 

        String r1 = "USRXXXX;
        String r2 = "Pass#word102";
        authenticateAD(r1,r2);
    


ldap.properties 文件

ad.domain=company.ad
ad.url=ldap://ADHO.COMPANY.NET:389/

SpringSecurityConfig.java 文件

package com.company.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;

import com.onezero.config.AuthenticationEntryPoint;

import java.util.Arrays;

@Configuration
@EnableWebSecurity
@PropertySource("classpath:ldap.properties")
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    private Environment env;

    @Bean
    public AuthenticationEntryPoint customAuthenticationEntry() throws Exception 
      return new AuthenticationEntryPoint();
    

    @Override
    public void configure(WebSecurity web) throws Exception 
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 


        http.authorizeRequests()
           .antMatchers("/welcome","/atm/**","/atm2/**","/**","/survey/**","/usrauth/**").authenticated()
           .and()
           .httpBasic()
           .authenticationEntryPoint(customAuthenticationEntry())
           .and()
           .exceptionHandling()
           .and()
           .csrf().disable()
           .sessionManagement()
           .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
    

    @Bean
    public AuthenticationManager authenticationManager() 
        return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
    

    @Bean
    public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() 
    ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(
    env.getProperty("ad.domain"), env.getProperty("ad.url"));

        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);




        return provider;

    



【问题讨论】:

【参考方案1】:

当服务器返回引用时,可以抛出 PartialResultException。这就是服务器说“我不知道你在说什么,但我知道谁知道”的方式。 this answer 中对选项有很好的解释。一是设置:

env.put(Context.REFERRAL, "follow");

这将告诉它将请求发送到服务器告诉我们去的任何地方。但我认为这不是一个好的解决方案。当只有一个会做的时候,你最终会发出两个网络请求。将配置更改为指向正确的位置是更好的选择。

找出它在抱怨什么的一种方法是检查PartialResultException 对象的resolvedName 属性。这应该会告诉您它会将您发送到哪里,并且您可以首先更改您的配置以指向那里。

我不是 Java 开发人员,所以这些猜测很多,但我确实知道 AD 的工作原理。还是试试吧。

【讨论】:

以上是关于Spring Security Active Directory LDAP 身份验证错误的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security Active Directory 错误凭据处理(错误 49)

Spring Security Active Directory LDAP 身份验证错误

Spring Security 3.1:Active Directory 身份验证和本地 DB 授权

具有 Active Directory 和数据库角色的 Spring Security

Spring Security - 在Spring Boot中针对LDAP使用Active Directory对用户进行身份验证

Spring Security 3 Active Directory 身份验证、数据库授权