Spring LDAP Overview – Spring LDAP概述

最后修改: 2017年 3月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

LDAP directory servers are read-optimized hierarchical data stores. Typically, they’re used for storing user-related information required for user authentication and authorization.

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

In this article, we’ll explore the Spring LDAP APIs to authenticate and search for users, as well as to create and modify users in the directory server. The same set of APIs can be used for managing any other type of entries in LDAP.

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

2. Maven Dependencies

2.Maven的依赖性

Let’s begin by adding the required Maven dependency:

让我们首先添加所需的Maven依赖性。

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

The latest version of this dependency can be found at spring-ldap-core.

该依赖关系的最新版本可以在spring-ldap-core找到。

3. Data Preparation

3.数据准备

For the purpose of this article, let’s first create the following LDAP entry:

为了本文的目的,让我们首先创建以下LDAP条目。

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

Under this node, we will create new users, modify existing users, authenticate existing users and search for information.

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

4. Spring LDAP APIs

4.Spring LDAP APIs

4.1. ContextSource & LdapTemplate Bean Definition

4.1.ContextSource & LdapTemplate Bean定义

ContextSource is used for creating the LdapTemplate. We will see the use of ContextSource during user authentication in the next section:

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 is used for creation and modification of LDAP entries:

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

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

4.2. Using Spring Boot

4.2.使用Spring Boot

When we are working on a Spring Boot project, we can use Spring Boot Starter Data Ldap dependency that will automatically instrument LdapContextSource and LdapTemplate for us. 

当我们在进行Spring Boot项目时,我们可以使用Spring Boot Starter Data Ldap依赖项,它将自动为我们提供LdapContextSourceLdapTemplate

To enable autoconfiguration, we need to ensure that we have the spring-boot-starter-data-ldap Starter or spring-ldap-core defined as a dependency in our pom.xml:

为了启用自动配置,我们需要确保我们有spring-boot-starter-data-ldap Starter或spring-ldap-core在我们的pom.xml中定义为一个依赖。

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

To connect to LDAP, we need to provide the connection settings in the application.properties:

为了连接到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

Then we are all set to inject the autoconfigured LdapTemplate into the required service class.

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

@Autowired
private LdapTemplate ldapTemplate;

4.3. User Authentication

4.3.用户认证

Let’s now implement a simple piece of logic to authenticate an existing user:

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

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

4.4. User Creation

4.4.用户创建

Next, let’s create a new user and store an SHA hash of the password in LDAP.

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

At the time of authentication, the LDAP server generates the SHA hash of the supplied password and compares it to the stored one:

在认证时,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() is a custom method which returns the Base64 encoded string of the SHA hash of the supplied password.

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

Finally, the bind() method of LdapTemplate is used to create an entry in the LDAP server.

最后,LdapTemplatebind()方法被用来在LDAP服务器中创建一个条目。

4.5. User Modification

4.5.用户修改

We can modify an existing user or entry with the following method:

我们可以用以下方法修改一个现有的用户或条目。

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);
}

The lookupContext() method is used to find the supplied user.

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

4.6. User Search

4.6.用户搜索

We can search for existing users using search filters:

我们可以使用搜索过滤器来搜索现有的用户。

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

The AttributesMapper is used to get the desired attribute value from the entries found. Internally, Spring LdapTemplate invokes the AttributesMapper for all the entries found and creates a list of the attribute values.

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

5. Testing

5.测试

spring-ldap-test provides an embedded LDAP server based on ApacheDS 1.5.5. To setup the embedded LDAP server for testing, we need to configure the following Spring bean:

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;
}

Let’s test our user search method with JUnit:

让我们用JUnit测试一下我们的用户搜索方法。

@Test
public void 
  givenLdapClient_whenCorrectSearchFilter_thenEntriesReturned() {
    List<String> users = ldapClient
      .search(SEARCH_STRING);
 
    assertThat(users, Matchers.containsInAnyOrder(USER2, USER3));
}

6. Conclusion

6.结论

In this article, we have introduced Spring LDAP APIs and developed simple methods for user authentication, user search, user creation and modification in an LDAP server.

在这篇文章中,我们介绍了Spring LDAP APIs,并开发了简单的方法用于LDAP服务器中的用户认证、用户搜索、用户创建和修改。

As always the full source code is available in this Github project. The tests are created under Maven profile “live” and hence can be run using the option “-P live”.

完整的源代码可在这个Github项目中找到。测试是在Maven配置文件 “live “下创建的,因此可以使用选项”-P live “运行。