Spring LDAP概述

2023/05/17

1. 概述

LDAP目录服务器是读取优化的分层数据存储。通常,它们用于存储用户身份验证和授权所需的用户相关信息。

在本文中,我们将探索Spring LDAP API来验证和搜索用户,以及在目录服务器中创建和修改用户。同一组API可用于管理LDAP中的任何其他类型的条目。

2. Maven依赖

让我们首先添加所需的Maven依赖项:


<dependency>
    <groupId>org.springframework.ldap</groupId>
    <artifactId>spring-ldap-core</artifactId>
    <version>2.3.6.RELEASE</version>
</dependency>

这个依赖的最新版本可以在spring-ldap-core 找到。

3. 数据准备

出于本文的目的,我们首先创建以下LDAP条目:

ou=users,dc=example,dc=com (objectClass=organizationalUnit)

在这个节点下,我们将创建新用户、修改现有用户、验证现有用户和搜索信息。

4. Spring LDAP API

4.1 ContextSource & LdapTemplate Bean定义

ContextSource用于创建LdapTemplate。我们将在下一节中看到ContextSource在用户认证过程中的使用:

@Bean
public LdapContextSource contextSource(){
        LdapContextSource contextSource=new LdapContextSource();

        contextSource.setUrl(env.getRequiredProperty("ldap.url"));
        contextSource.setBase(env.getRequiredProperty("ldap.partitionSuffix"));
        contextSource.setUserDn(env.getRequiredProperty("ldap.principal"));
        contextSource.setPassword(env.getRequiredProperty("ldap.password"));

        return contextSource;
        }

LdapTemplate用于创建和修改LDAP条目:

@Bean
public LdapTemplate ldapTemplate(){
        return new LdapTemplate(contextSource());
        }

4.2 使用Spring Boot

当我们处理Spring Boot项目时,我们可以使用Spring Boot Starter Data Ldap 依赖项,它会自动为我们检测LdapContextSource和LdapTemplate

要启用自动配置,我们需要确保在pom.xml中将spring-boot-starter-data-ldap或spring-ldap-core定义为依赖项:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>

要连接到LDAP,我们需要在application.properties中提供连接设置:

spring.ldap.url=ldap://localhost:18889
spring.ldap.base=dc=example,dc=com
spring.ldap.username=uid=admin,ou=system
spring.ldap.password=secret

然后我们可以将自动配置的LdapTemplate注入到所需的服务类中。

@Autowired
private LdapTemplate ldapTemplate;

4.3 用户身份验证

现在让我们实现一个简单的逻辑来验证现有用户:

public void authenticate(String username,String password){
        contextSource
        .getContext("cn="+username+",ou=users,"+env.getRequiredProperty("ldap.partitionSuffix"),password);
        }

4.4 用户创建

接下来,让我们创建一个新用户并将密码的SHA哈希存储在LDAP中。

在身份验证时,LDAP服务器生成所提供密码的SHA哈希,并将其与存储的密码进行比较:

public void create(String username,String password){
        Name dn=LdapNameBuilder
        .newInstance()
        .add("ou","users")
        .add("cn",username)
        .build();
        DirContextAdapter context=new DirContextAdapter(dn);

        context.setAttributeValues("objectclass",
        new String[]{"top","person","organizationalPerson","inetOrgPerson"});
        context.setAttributeValue("cn",username);
        context.setAttributeValue("sn",username);
        context.setAttributeValue("userPassword",digestSHA(password));

        ldapTemplate.bind(context);
        }

digestSHA()是一个自定义方法,它返回所提供密码的SHA哈希的Base64编码字符串。

最后,使用LdapTemplate的bind()方法在LDAP服务器中创建一个条目。

4.5 用户修改

我们可以使用以下方法修改现有用户或条目:

public void modify(String username,String password){
        Name dn=LdapNameBuilder.newInstance()
        .add("ou","users")
        .add("cn",username)
        .build();
        DirContextOperations context=ldapTemplate.lookupContext(dn);

        context.setAttributeValues("objectclass",
        new String[]{"top","person","organizationalPerson","inetOrgPerson"});
        context.setAttributeValue("cn",username);
        context.setAttributeValue("sn",username);
        context.setAttributeValue("userPassword",digestSHA(password));

        ldapTemplate.modifyAttributes(context);
        }

lookupContext()方法用于查找提供的用户。

4.6 用户搜索

我们可以使用搜索过滤器搜索现有用户:

public List<String> search(String username){
        return ldapTemplate
        .search("ou=users","cn="+username,(AttributesMapper<String>)attrs->(String)attrs.get("cn").get());
        }

AttributesMapper用于从找到的条目中获取所需的属性值。在内部,Spring LdapTemplate为找到的所有条目调用AttributesMapper并创建属性值列表。

5. 测试

spring-ldap-test提供了一个基于ApacheDS 1.5.5的嵌入式LDAP服务器。要设置嵌入式LDAP服务器进行测试,我们需要配置以下Spring bean:

@Bean
public TestContextSourceFactoryBean testContextSource(){
        TestContextSourceFactoryBean contextSource=new TestContextSourceFactoryBean();

        contextSource.setDefaultPartitionName(env.getRequiredProperty("ldap.partition"));
        contextSource.setDefaultPartitionSuffix(env.getRequiredProperty("ldap.partitionSuffix"));
        contextSource.setPrincipal(env.getRequiredProperty("ldap.principal"));
        contextSource.setPassword(env.getRequiredProperty("ldap.password"));
        contextSource.setLdifFile(resourceLoader.getResource(env.getRequiredProperty("ldap.ldiffile")));
        contextSource.setPort(Integer.valueOf(env.getRequiredProperty("ldap.port")));
        return contextSource;
        }

让我们用JUnit测试我们的用户搜索方法:

@Test
public void givenLdapClient_whenCorrectSearchFilter_thenEntriesReturned(){
        List<String> users=ldapClient.search(SEARCH_STRING);

        assertThat(users,Matchers.containsInAnyOrder(USER2,USER3));
        }

6. 总结

在本文中,我们介绍了Spring LDAP API,并开发了用于在LDAP服务器中进行用户身份验证、用户搜索、用户创建和修改的简单方法。

与往常一样,完整的源代码在此Github项目 中可用。测试是在Maven Profile “live”下创建的,因此可以使用选项“-P live”运行。

与往常一样,本教程的完整源代码可在GitHub 上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章