如何在忽略NameNotFoundException的同时使用ldap对用户进行身份验证?

时间:2017-07-24 09:47:33

标签: java spring security exception spring-security

我正在使用Spring Security为Web应用程序创建登录页面。用户已在Active Directory中注册。

以下是我正在使用的代码:

public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception{
    authenticationManagerBuilder.ldapAuthentication()
            .contextSource().url("ldap:MyLdap")
            .root("ou=MyOu,dc=MyDC,dc=net")
            .port(389)
            .managerDn("cn=MyCN,ou=MyOU,ou=MyOU2,dc=MyDC,dc=net").managerPassword("MyPass")
            .and()
            .userSearchBase("dc=MyDC,dc=net")
            .userSearchFilter("(sAMAccountName={0})");
}

用户搜索过滤器设置为sAMAccountName,因为这是我公司的Active Directory中的唯一标识符。

我能够从Active Directory成功检索到正确的用户,但我在NameNotFoundException类中抛出了LdapTemplate。该类cas属性IgnoreNameNotFoundException。如果我在调试时将此属性设置为true,则登录正确,否则我会收到错误并且登录失败。

如何从代码中设置此属性?或者我在配置中做错了什么?

编辑:

这是堆栈跟踪:

org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-03100213, problem 2001 (NO_OBJECT), data 0, best match of:
""
]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-03100213, problem 2001 (NO_OBJECT), data 0, best match of:
""
]; remaining name ""
at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:183) ~[spring-ldap-core-2.3.1.RELEASE.jar:2.3.1.RELEASE]
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:376) ~[spring-ldap-core-2.3.1.RELEASE.jar:2.3.1.RELEASE]

2 个答案:

答案 0 :(得分:1)

根据此documentationignore-name-not-found属性具有魔力。如果您可以使用基于XML的配置覆盖它,那应该这样做。我无法为此找到合适的程序覆盖,如果我找到它,我会更新。

另一种方法是创建自己的bean,扩展LDAP Provider,但重写同一属性并注入它。这应该可行,但您需要知道如何使用父类,因为它可能会破坏某些功能。

答案 1 :(得分:0)

我找到了一种使用自定义LdapTemplate的方法,因为我必须定义一个自定义的AuthenticationProvider。

以下是WebSecurityConfigurerAdapter中的代码:

@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception{
    LdapAuthenticationProvider ldapProvider=new LdapAuthenticationProvider();
    authenticationManagerBuilder.authenticationProvider(ldapProvider);
}

以下是AuthenticationProvider中的代码:

@Component
public class LdapAuthenticationProvider implements AuthenticationProvider {

@Override
public Authentication authenticate(Authentication authentication) {
    String name = authentication.getName();
    String password = authentication.getCredentials().toString();
    LdapTemplate ldapTemplate=ldapTemplate();
    Filter filter = new EqualsFilter("sAMAccountName", name);
    boolean authed = ldapTemplate.authenticate("", filter.encode(), password);
    //ldapTemplate.getContextSource().getContext(password, name);
    if(!authed){
        return null;
    }
    return new UsernamePasswordAuthenticationToken(name,password,new ArrayList<>());
}

@Bean
public LdapTemplate ldapTemplate(){
    LdapTemplate ldapTemplate=new LdapTemplate(contextSource());
    ldapTemplate.setIgnoreNameNotFoundException(true);
    return ldapTemplate;
}

@Bean 
LdapContextSource contextSource(){
    LdapContextSource contextSource=new LdapContextSource();
    contextSource.setUrl("");
    //all of the private configurations
    contextSource.afterPropertiesSet();
    return contextSource;
}