简介

本节提供了一个关于 Spring LDAP 的相对快速的介绍。它包含以下内容

概览

Spring LDAP 旨在简化 Java 中的 LDAP 编程。库提供的一些功能包括

  • JdbcTemplate 样式的模板,简化了 LDAP 编程。

  • JPA 或 Hibernate 样式的基于注解的对象和目录映射。

  • Spring Data 存储库支持,包括对 QueryDSL 的支持。

  • 简化构建 LDAP 查询和可分辨名称的实用工具。

  • 正确的 LDAP 连接池。

  • 客户端 LDAP 补偿事务支持。

传统 Java LDAP 与 LdapClient

考虑一个方法,该方法应该搜索某个存储以查找所有人员并将其姓名返回到列表中。通过使用 JDBC,我们将创建一个连接并使用语句运行查询。然后,我们将遍历结果集并检索我们想要的,将其添加到列表中。

使用 JNDI 对 LDAP 数据库进行操作,我们将创建一个上下文并使用搜索过滤器执行搜索。然后,我们将遍历生成的命名枚举,检索我们想要的属性,并将其添加到列表中。

在 Java LDAP 中实现此人员姓名搜索方法的传统方法类似于下一个示例。请注意标有粗体的代码 - 这是实际执行与方法业务目的相关的任务的代码。其余的是管道。

public class TraditionalPersonRepoImpl implements PersonRepo {
   public List<String> getAllPersonNames() {
      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
      env.put(Context.PROVIDER_URL, "ldap://127.0.0.1:389/dc=example,dc=com");

      DirContext ctx;
      try {
         ctx = new InitialDirContext(env);
      } catch (NamingException e) {
         throw new RuntimeException(e);
      }

      List<String> list = new LinkedList<String>();
      NamingEnumeration results = null;
      try {
         SearchControls controls = new SearchControls();
         controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
         results = ctx.search("", "(objectclass=person)", controls);

         while (results.hasMore()) {
            SearchResult searchResult = (SearchResult) results.next();
            Attributes attributes = searchResult.getAttributes();
            Attribute attr = attributes.get("cn");
            String cn = attr.get().toString();
            list.add(cn);
         }
      } catch (NameNotFoundException e) {
         // The base context was not found.
         // Just clean up and exit.
      } catch (NamingException e) {
         throw new RuntimeException(e);
      } finally {
         if (results != null) {
            try {
               results.close();
            } catch (Exception e) {
               // Never mind this.
            }
         }
         if (ctx != null) {
            try {
               ctx.close();
            } catch (Exception e) {
               // Never mind this.
            }
         }
      }
      return list;
   }
}

通过使用 Spring LDAP AttributesMapperLdapClient 类,我们可以使用以下代码获得完全相同的功能

import static org.springframework.ldap.query.LdapQueryBuilder.query;

public class PersonRepoImpl implements PersonRepo {
   private LdapClient ldapClient;

   public void setLdapClient(LdapClient ldapClient) {
      this.ldapClient = ldapClient;
   }

   public List<String> getAllPersonNames() {
      return ldapClient.search().query(
            query().where("objectclass").is("person")
         ).toObject((Attributes attrs) ->
            attrs.get("cn").get().toString();
         );
   }
}

样板代码的数量明显少于传统示例。LdapClient 搜索方法确保创建 DirContext 实例,执行搜索,使用给定的 AttributesMapper 将属性映射到字符串,在内部列表中收集字符串,最后返回列表。它还确保正确关闭 NamingEnumerationDirContext,并处理可能发生的任何异常。

当然,作为 Spring Framework 的子项目,我们使用 Spring 配置我们的应用程序,如下所示

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:ldap="http://www.springframework.org/schema/ldap"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/ldap https://www.springframework.org/schema/ldap/spring-ldap.xsd">

   <ldap:context-source
          url="ldap://127.0.0.1:389"
          base="dc=example,dc=com"
          username="cn=Manager"
          password="secret" />

   <bean id="ldapClient" class="org.springframework.ldap.core.LdapClient" factory-method="create">
        <constructor-arg ref="contextSource" />
    </bean>

   <bean id="personRepo" class="com.example.repo.PersonRepoImpl">
      <property name="ldapClient" ref="ldapClient" />
   </bean>
</beans>
要使用自定义 XML 命名空间配置 Spring LDAP 组件,您需要在 XML 声明中包含对该命名空间的引用,如前面的示例所示。

2.2 中的新增功能

有关 2.2 的完整详细信息,请参阅 2.2.0.RC1 的更改日志。Spring LDAP 2.2 的亮点如下

  • #415:添加了对 Spring 5 的支持

  • #399:嵌入式 UnboundID LDAP 服务器支持

  • #410:添加了 Commons Pool 2 支持的文档

2.1 中的新增功能

有关 2.1 的完整详细信息,请参阅 2.1.0.RC12.1.0 的更改日志。Spring LDAP 2.1 的亮点如下。

  • #390:添加了 Spring Data Hopper 支持

  • #351:添加了对 commons-pool2 的支持

  • #370:在 XML 命名空间中添加了对属性占位符的支持

  • #392:添加了文档测试支持

  • #401:添加了切换到 assertj 的功能

  • 从 JIRA 迁移到 GitHub Issues

  • 添加了 Gitter 聊天

2.0 中的新增功能

虽然在 2.0 版本中对 Spring LDAP API 进行了相当重大的现代化改造,但我们已非常小心地确保尽可能地向后兼容。在使用 2.0 库时,与 Spring LDAP 1.3.x 兼容的代码(除了少数例外)应该能够编译和运行,而无需任何修改。

例外情况是一小部分类已移动到新的包中,以便能够进行一些重要的重构。移动的类通常不是预期公共 API 的一部分,迁移过程应该很顺利。如果在升级后找不到 Spring LDAP 类,则应在 IDE 中整理导入。

但是,您应该期望遇到一些弃用警告,并且还有许多其他 API 改进。为了充分利用 2.0 版本,建议您远离已弃用的类和方法,并迁移到新的、改进的 API 实用工具。

以下列表简要描述了 Spring LDAP 2.0 中最重要的更改

  • Spring LDAP 现在需要 Java 6。从 2.0 及更高版本的 Spring 版本仍然受支持。

  • 核心 API 已使用 Java 5+ 功能(如泛型和可变参数)进行了更新。因此,整个 spring-ldap-tiger 模块已被弃用,我们建议您迁移到使用核心 Spring LDAP 类。核心接口的参数化会导致现有代码出现大量编译警告,我们建议您采取适当措施消除这些警告。

  • ODM(对象目录映射)功能已移至核心,并且 LdapOperationsLdapTemplate 中有新的方法使用此自动转换到和从 ODM 注解的类。有关更多信息,请参阅 对象目录映射 (ODM)

  • 现在(最终)提供了自定义 XML 命名空间来简化 Spring LDAP 的配置。有关更多信息,请参阅 [配置]

  • Spring LDAP 现在提供对 Spring Data 存储库和 QueryDSL 的支持。有关更多信息,请参阅 Spring LDAP 存储库

  • Name 实例作为属性值现在在 DirContextAdapter 和 ODM 中关于可分辨名称相等性方面得到正确处理。有关更多信息,请参阅 DirContextAdapter 和可分辨名称作为属性值ODM 和可分辨名称作为属性值

  • DistinguishedName 和相关类已弃用,取而代之的是标准 Java LdapName。有关库在使用 LdapName 对象时如何提供帮助的信息,请参阅 动态构建可分辨名称

  • 添加了流畅的 LDAP 查询构建支持。这使得在 Spring LDAP 中使用 LDAP 搜索时,编程体验更加愉悦。有关 LDAP 查询构建器支持的更多信息,请参见构建 LDAP 查询高级 LDAP 查询

  • LdapTemplate 中旧的 authenticate 方法已弃用,取而代之的是几个新的 authenticate 方法,这些方法使用 LdapQuery 对象并在身份验证失败时抛出异常,使用户更容易找出导致身份验证尝试失败的原因。

  • 已改进和更新了示例,以利用 2.0 中的功能。我们投入了大量精力来提供一个有用的LDAP 用户管理应用程序示例。

打包概述

至少,要使用 Spring LDAP,您需要以下内容

  • spring-ldap-core:Spring LDAP 库

  • spring-core:框架内部使用的各种实用程序类

  • spring-beans:用于操作 Java Bean 的接口和类

  • slf4j:一个简单的日志记录外观,在内部使用

除了必需的依赖项外,某些功能还需要以下可选依赖项

  • spring-data-ldap:存储库支持等的基础设施

  • spring-context:如果您的应用程序通过使用 Spring Application Context 进行连接,则需要此项。spring-context 使应用程序对象能够通过使用一致的 API 获取资源。如果您计划使用 BaseLdapPathBeanPostProcessor,则绝对需要此项。

  • spring-tx:如果您计划使用客户端补偿事务支持,则需要此项。

  • spring-jdbc:如果您计划使用客户端补偿事务支持,则需要此项。

  • commons-pool:如果您计划使用池功能,则需要此项。

  • spring-batch:如果您计划将 LDIF 解析功能与 Spring Batch 一起使用,则需要此项。

spring-data-ldap 会传递添加 spring-repository.xsd,而 spring-ldap.xsd 会使用它。因此,即使未使用 Spring Data 的功能集,Spring LDAP 的 XML 配置支持也需要此依赖项。

入门

示例提供了一些关于如何将 Spring LDAP 用于常见用例的有用示例。

支持

如果您有任何疑问,请在Stack Overflow 上使用 spring-ldap 标签提问。项目网页是spring.io/spring-ldap/

致谢

启动 Spring LDAP 项目时的初始工作由Jayway赞助。该项目的当前维护由Pivotal资助,Pivotal 后来被VMware收购。

感谢Structure101提供了开源许可证,这对于保持项目的结构井然有序非常有用。