通过 Spring Security 的 Active Directory 身份验证返回由 LDAP 引起的有效用户的错误凭据:错误代码 49

Posted

技术标签:

【中文标题】通过 Spring Security 的 Active Directory 身份验证返回由 LDAP 引起的有效用户的错误凭据:错误代码 49【英文标题】:Active Directory authentication via spring security returns bad credential for valid users caused by LDAP: error code 49 【发布时间】:2019-05-21 07:08:06 【问题描述】:

我正在开发一个 spring boot maven 项目来验证具有用户名和密码的用户。如果用户通过了身份验证,微服务需要返回 true/false。

SecurityConfiguration.java

package com.app.config;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter

    private static final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);

    private String url = "ldaps://org.abc.in:3387";
    private String domain = "org.abc.in";
    private String userDNPattern = "CN=pan,OU=Users,OU=UCV,DC=org,DC=abc,DC=in";

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                        .authorizeRequests().antMatchers("/", "logout").permitAll();

    


     @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 adProvider = new ActiveDirectoryLdapAuthenticationProvider(domain, url);
            adProvider.setConvertSubErrorCodesToExceptions(true);
            adProvider.setUseAuthenticationRequestCredentials(true);
            //adProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
            return adProvider;
        


我通过传递用户名和密码调用以下方法

public Authentication signin(String username, String password) throws Exception
        Authentication auth = new UsernamePasswordAuthenticationToken("pan@abc.in", "password");
        return authenticationManager.authenticate(auth); // this line gives Bad Credential error
    

调用方法 authenticationManager.authenticate(auth) 时出现以下错误

ctiveDirectoryLdapAuthenticationProvider : Active Directory authentication failed: Supplied password was invalid
org.springframework.security.authentication.BadCredentialsException: Bad credentials
    at org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider.badCredentials(ActiveDirectoryLdapAuthenticationProvider.java:308)

原因:org.springframework.security.ldap.authentication.ad.ActiveDirectoryAuthenticationException:[LDAP:错误代码 49 - 80090308:LdapErr:DSID-0C09042F,注释:AcceptSecurityContext 错误,数据 52e,v2580

我浏览了以下链接: javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]

Active Directory Authentication using Spring Security 3.2, Spring Ldap 2.0 and JavaConfig

LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db1

基于上述链接,我尝试了 setAuthoritiesMapper 并通过了 NullAuthoritiesMapper,因为我没有任何权限进行映射。

adProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());

我尝试对userDNPattern = "CN=pan,OU=Users,OU=UCV,DC=org,DC=abc,DC=in";进行更改,但没有成功。 CN= pan 是我的用户名

我可以使用上述 url、域、userDnPattern 和密码访问 Apache Active Directory。我需要对密码进行编码吗?

【问题讨论】:

这是您的完整用户名,包括域“pan@abc.in”吗? @slimane 用户名是 pan,rest 是域 【参考方案1】:

您的域是“org.abc.in”。 将“pan@abc.in”更改为“pan”,ActiveDirectoryLdapAuthenticationProvider 将自动将您的域添加到其中,因为您在创建过程中已经指定了它(“org.abc.in”)。

【讨论】:

我的域名设置错误。它必须是 abc.in 而不是 org.abc.in【参考方案2】:

这可能不是唯一的问题,但这肯定是其中的一部分:

adProvider.setSearchFilter(userDNPattern);

该方法采用 LDAP 查询来查找用户,而不是 DN。 documentation for setSearchFilter() 表示默认是这样的:

(&(objectClass=user)(userPrincipalName=0))

这将采用您提供的用户名,并找到具有该userPrincipalName(“username@domain.com”格式)的用户。

如果这是你想要的,那么你根本不需要打电话给setSearchFilter()

如果您希望用户能够仅使用用户名 (sAMAccountName) 登录,那么您可以使用:

adProvider.setSearchFilter("(&(objectClass=user)(sAMAccountName=0))");

更新:我认为您还有其他一些问题:

private String url = "ldaps://org.abc.in:3387";
private String domain = "org.abc.in";

首先,ldaps:// 实际上是无效的。只需使用ldap://。如果指定的端口使用 SSL,那么它将进行 SSL 握手。

另外,您将域设置为org.abc.in,但当您登录时,您使用的是@abc.in。您指定的domain 会附加到您指定的登录用户名,因此它会尝试使用pan@abc.in@org.abc.in 让您登录,这当然是行不通的。您最好将domain 设置为null,这样它就不会在以后尝试附加任何内容。但这意味着您的用户需要使用username@abc.in 格式登录。

【讨论】:

我已删除 adProvider.setSearchFilter(userDNPattern);现在因为它不会对输出进行任何更改。 authenticationManager.authenticate(auth) 仍然返回 - 凭据错误 我用更多信息更新了我的答案。但也有这个:***.com/a/16591738/1202807 SSL 握手没有问题。私有字符串 url = "ldaps://org.abc.in:3387";也可以。握手按预期进行。我的域没有按照你的解释正确设置。我没有将 org.abc.in 设置为 abc.in 并仅传递用户名 pan : Authentication auth = new UsernamePasswordAuthenticationToken("pan", "password");这按预期工作。

以上是关于通过 Spring Security 的 Active Directory 身份验证返回由 LDAP 引起的有效用户的错误凭据:错误代码 49的主要内容,如果未能解决你的问题,请参考以下文章

如何使用spring-security通过用户名和密码登录?

Spring Security 入门(1-9)Spring Security - 拦截 url

Spring Security 入门(1-13)Spring Security - Session管理

通过 Active Directory LDAP 使用 Spring-Security 进行身份验证

Spring Security——通过密码和临时密码登录

无法通过Spring Security中的登录页面