如何使用 Spring LDAP 对 LDAP 进行身份验证

时间:2021-06-17 23:14:01

标签: spring spring-ldap

我是 Spring Boot 的新手,有一个 Jndi 代码,可以很好地向 LDAP 服务器进行身份验证。但是现在我想将我的代码迁移到 Spring LDAP,但是每次都得到 [LDAP: error code 49 - 80090308: LdapErr: DSID-0C09044E, comment: AcceptSecurityContext error, data 52e, v2580]。

所以我的 JNDI 代码看起来像这样:

    public void connect(String userName, String pwd) throws NamingException, IllegalStateException {
    Hashtable<String, String> env = new Hashtable<String, String>();
    try {
        env.put(LdapContext.CONTROL_FACTORIES, "com.sun.jndi.ldap.ControlFactory");
        env.put(Context.SECURITY_PRINCIPAL, userName+"@domain.net);
        env.put(Context.SECURITY_CREDENTIALS, pwd);
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL,  "ldap://server:389");
        env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
        context = new InitialDirContext(env); 
    } finally {
        if (context !=null) {
            log.info("Authentication successfull");
            try {
                context.close();
                context = null;
            } catch(NamingException ne) {
                log.error(ne.getMessage());
                ne.printStackTrace();
            }
        } else {
            throw new  IllegalStateException("Can't obtain LDAP context");
        }
    }
}

非常简单。

到目前为止,我已经在我的 Spring boot application.properties 文件中配置了以下内容:

spring.ldap.urls=Ldap://server:389
spring.ldap.embedded.credential.username=cn=ceadministrator
spring.ldap.embedded.credential.password=******
spring.ldap.embedded.base-dn=dc=domain,dc=net

让Spring Ldap管理连接和初始化

实现此目的是为了搜索某些用户:

    public List<User> getUser(String userName) throws NamingException, LDAPException {
    LdapQuery query = LdapQueryBuilder.query()
                        .searchScope(SearchScope.SUBTREE)
                        .timeLimit(3000)
                        .countLimit(10)
                        .attributes("cn")
                        .base(ldapConfig.getBase())
                        .where("objectClass").is("user")
                        .and("sAMAccountName").is(userName);
                        
    log.info("ldapTemplate: "+ldapTemplate);
    return ldapTemplate.search(query, new UserAttributesMapper());
}

private class UserAttributesMapper implements AttributesMapper<User> {
    @Override
    public User mapFromAttributes(Attributes attributes) throws NamingException {
        User user = new User();
        if (attributes == null) {
            log.warn("atttrs null");
            return user;
        }
        user.setFirstName((String) attributes.get("cn").get());
        Attribute sn = attributes.get("sAMAccountName");
        if (sn != null) {
            user.setUserName((String) sn.get());
        }
        return user;
    }
}

但它抛出一个AutheticationException:

javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C09044E, comment: AcceptSecurityContext error, data 52e, v2580

我错过了什么/做错了什么?...请帮忙

1 个答案:

答案 0 :(得分:0)

我终于明白了。

我发现 SpringBoot 提供了一个嵌入式 LDAP 服务器,插入 “unboundid-ldapsdk”依赖项到您的 pom.xml 文件中。这不是我想要的场景,因为我已经有一个生产环境 LDAP 服务器要连接。

所以我只需要像这样在 application.properties 文件中配置以下属性:

spring.ldap.urls=Ldap://192.17.1.4:389
spring.ldap.base=ou=Organization,OU=Some users unit,dc=depr,dc=net
spring.ldap.username=administrator
spring.ldap.password=SomePassword

了解“Spring.ldap.base”是我开始搜索的基础,与我的管理员凭据无关。