Introduction

本节提供了 Spring LDAP 的快速简介,包括以下内容:

This section offers a relatively quick introduction to Spring LDAP. It includes the following content:

Overview

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

Spring LDAP is designed to simplify LDAP programming in Java. Some of the features provided by the library are:

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

  • JdbcTemplate-style template simplifications to LDAP programming.

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

  • JPA- or Hibernate-style annotation-based object and directory mapping.

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

  • Spring Data repository support, including support for QueryDSL.

  • 简化 LDAP 查询和识别名的构建的实用程序。

  • Utilities to simplify building LDAP queries and distinguished names.

  • Proper LDAP connection pooling.

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

  • Client-side LDAP compensating transaction support.

Traditional Java LDAP versus LdapClient

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

Consider a method that should search some storage for all persons and return their names in a list. By using JDBC, we would create a connection and run a query by using a statement. We would then loop over the result set and retrieve the column we want, adding it to a list.

通过使用 JNDI 针对一个 LDAP 数据库工作,我们将创建一个 上下文,并使用 搜索过滤器 执行一个 搜索。然后我们将遍历由此产生的 命名枚举,检索所需的 属性,并将它添加到列表中。

Working against an LDAP database with JNDI, we would create a context and perform a search by using a search filter. We would then loop over the resulting naming enumeration, retrieve the attribute we want, and add it to a list.

使用 Java LDAP 实现人员姓名搜索方法的传统方法如下例所示。注意用*加粗*标记的代码 - 这是执行与方法业务目的相关任务的实际代码。其余部分是管道。

The traditional way of implementing this person-name search method in Java LDAP looks like the next example. Note the code marked bold - this is the code that actually performs tasks related to the business purpose of the method. The rest is plumbing.

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://localhost: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 类,我们使用以下代码获得了完全相同的功能:

By using the Spring LDAP AttributesMapper and LdapClient classes, we get the exact same functionality with the following code:

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,并处理可能发生的任何异常。

The amount of boilerplate code is significantly less than in the traditional example. The LdapClient search method makes sure a DirContext instance is created, performs the search, maps the attributes to a string by using the given AttributesMapper, collects the strings in an internal list, and, finally, returns the list. It also makes sure that the NamingEnumeration and DirContext are properly closed and takes care of any exceptions that might happen.

当然,由于这是一个 Spring 框架子项目,因此我们使用 Spring 来配置我们的应用程序,如下所示:

Naturally, this being a Spring Framework sub-project, we use Spring to configure our application, as follows:

<?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://localhost: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 声明中包含这些名称空间的引用,如前面的示例所示。

To use the custom XML namespace to configure the Spring LDAP components, you need to include references to this namespace in your XML declaration, as in the preceding example.

What’s new in 2.2

有关 2.2 的完整详细信息,请参阅以下变更日志:@17"。Spring LDAP 2.2 的亮点如下:

For complete details of 2.2, see the changelog for 2.2.0.RC1. The highlights of Spring LDAP 2.2 are as follows:

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

  • #415: Added support for Spring 5

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

  • #399: Embedded UnboundID LDAP Server support

  • #410:增加了用于 Commons Pool 2 支持的文档

  • #410: Added documentation for the Commons Pool 2 Support

What’s new in 2.1

有关 2.1 的完整详细信息,请参阅以下变更日志:@18" 和 @"19"。Spring LDAP 2.1 的亮点如下。

For complete details of 2.1, see the changelog for 2.1.0.RC1 and for 2.1.0 The highlights of Spring LDAP 2.1 are as follows.

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

  • #390: Added Spring Data Hopper support

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

  • #351: Added support for commons-pool2

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

  • #370: Added support property placeholders in the XML Namespace

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

  • #392: Added document Testing Support

  • #401:增加了一个断言的切换

  • #401: Added a switch to assertj

  • 从 JIRA 迁移到 GitHub Issues

  • Migrated from JIRA to GitHub Issues

  • Added Gitter Chat

What’s new in 2.0

尽管 Spring LDAP API 在 2.0 版本中进行了相当重要的现代化改造,但已非常小心地确保了向后兼容性,尽可能做到。使用 Spring LDAP 1.3.x 的代码应该在无任何修改的情况下与 2.0 库一起编译并运行,只有少数例外。

While quite significant modernizations have been made to the Spring LDAP API in version 2.0, great care has been taken to ensure backward compatibility as far as possible. Code that works with Spring LDAP 1.3.x should, with few exceptions, compile and run when you use the 2.0 libraries without any modifications.

例外是一些类,它们已移动到新包以便让几个重要的重构成为可能。移动的类通常不是预期公共 API 的一部分,而迁移过程应该很平稳。每当在升级后找不到某个 Spring LDAP 类时,都应该组织 IDE 中的导入。

The exception is a small number of classes that have been moved to new packages in order to make a couple of important refactorings possible. The moved classes are typically not part of the intended public API, and the migration procedure should be smooth. Whenever a Spring LDAP class cannot be found after upgrade, you should organize the imports in your IDE.

不过,您应该会遇到一些弃用警告,还有许多其他 API 改进。有关充分利用 2.0 的建议是:放弃使用已弃用的类和方法,并迁移到新的改进版 API 实用程序。

You should expect to encounter some deprecation warnings, though, and there are also a lot of other API improvements. The recommendation for getting as much as possible out of the 2.0 version is to move away from the deprecated classes and methods and migrate to the new, improved API utilities.

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

The following list briefly describes the most important changes in Spring LDAP 2.0:

  • Java 6 现在是 Spring LDAP 所必需的。2.0 及其之后的 Spring 版本仍然支持。

  • Java 6 is now required by Spring LDAP. Spring versions starting at 2.0 and up are still supported.

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

  • The central API has been updated with Java 5+ features such as generics and varargs. As a consequence, the entire spring-ldap-tiger module has been deprecated, and we encourage you to migrate to using the core Spring LDAP classes. The parameterization of the core interfaces causes lots of compilation warnings on existing code, and we encourage you to take appropriate action to get rid of these warnings.

  • ODM(对象目录映射)功能已移至核心,且 LdapOperationsLdapTemplate 中有使用这种自动翻译(往返于 ODM 注释的类)的新方法。请参阅 Object-Directory Mapping (ODM) 以了解更多信息。

  • The ODM (Object-Directory Mapping) functionality has been moved to core, and there are new methods in LdapOperations and LdapTemplate that use this automatic translation to and from ODM-annotated classes. See Object-Directory Mapping (ODM) for more information.

  • 最终提供了自定义 XML 命名空间来简化 Spring LDAP 的配置。有关详细信息,请参阅 [configuration]

  • A custom XML namespace is now (finally) provided to simplify configuration of Spring LDAP. See [configuration] for more information.

  • Spring LDAP 现在为 Spring Data Repository 和 QueryDSL 提供支持。有关详细信息,请参阅 Spring LDAP Repositories

  • Spring LDAP now provides support for Spring Data Repository and QueryDSL. See Spring LDAP Repositories for more information.

  • 现在以 DirContextAdapter 和 ODM 中识别名相等性方面正确处理 Name 实例作为属性值。有关详细信息,请参阅 DirContextAdapter and Distinguished Names as Attribute ValuesODM and Distinguished Names as Attribute Values

  • Name instances as attribute values are now handled properly with regards to distinguished name equality in DirContextAdapter and ODM. See DirContextAdapter and Distinguished Names as Attribute Values and ODM and Distinguished Names as Attribute Values for more information.

  • DistinguishedName 已弃用,其相关类已弃用,支持标准的 Java LdapName。有关库在处理 LdapName 对象时的帮助的信息,请参阅 Dynamically Building Distinguished Names

  • DistinguishedName and associated classes have been deprecated in favor of the standard Java LdapName. See Dynamically Building Distinguished Names for information on how the library helps when working with LdapName objects.

  • 增加了流利的 LDAP 查询构建支持。当处理 Spring LDAP 中的 LDAP 搜索时,这将带来更愉快的编程体验。有关 LDAP 查询构建程序支持的更多信息,请参阅 Building LDAP QueriesAdvanced LDAP Queries

  • Fluent LDAP query building support has been added. This makes for a more pleasant programming experience when working with LDAP searches in Spring LDAP. See Building LDAP Queries and Advanced LDAP Queries for more information about the LDAP query builder support.

  • LdapTemplate 中旧的 authenticate 方法已弃用,支持几个新的 authenticate 方法,这些方法使用 LdapQuery 对象和 throw exceptions 处理身份验证失败,使用户更容易找到导致身份验证尝试失败的因素。

  • The old authenticate methods in LdapTemplate have been deprecated in favor of a couple of new authenticate methods that work with LdapQuery objects and throw exceptions on authentication failure, making it easier for the user to find out what caused an authentication attempt to fail.

  • samples 已得到优化和更新,以便使用 2.0 中的功能。已付出大量努力提供了有用 的 LDAP user management application 示例。

  • The samples have been polished and updated to make use of the features in 2.0. Quite a bit of effort has been put into providing a useful example of an LDAP user management application.

Packaging Overview

最少情况下,要使用 Spring LDAP,您需要以下内容:

At a minimum, to use Spring LDAP you need the following:

  • spring-ldap-core:Spring LDAP 库

  • spring-ldap-core: The Spring LDAP library

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

  • spring-core: Miscellaneous utility classes used internally by the framework

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

  • spring-beans: Interfaces and classes for manipulating Java beans

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

  • slf4j: A simple logging facade, used internally

除了必需的依赖项之外,还需要以下可选依赖项来实现特定功能:

In addition to the required dependencies, the following optional dependencies are required for certain functionality:

  • spring-data-ldap:基础架构用于存储库支持等

  • spring-data-ldap: Base infrastructure for repository support and so on

  • spring-context:如果使用 Spring 应用上下文对应用进行连接,则需要。spring-context`会增加应用对象以一致的 API 获取资源的能力。如果你计划使用 `BaseLdapPathBeanPostProcessor,这肯定是必需的。

  • spring-context: Needed if your application is wired up by using the Spring Application Context. spring-context adds the ability for application objects to obtain resources by using a consistent API. It is definitely needed if you plan to use the BaseLdapPathBeanPostProcessor.

  • spring-tx:如果你打算使用客户端补偿事务支持,则需要。

  • spring-tx: Needed if you plan to use the client-side compensating transaction support.

  • spring-jdbc:如果你打算使用客户端补偿事务支持,则需要。

  • spring-jdbc: Needed if you plan to use the client-side compensating transaction support.

  • commons-pool:如果你打算使用连接池功能,则需要。

  • commons-pool: Needed if you plan to use the pooling functionality.

  • spring-batch:如果你打算将 LDIF 解析功能与 Spring Batch 一起使用,则需要。

  • spring-batch: Needed if you plan to use the LDIF parsing functionality together with Spring Batch.

spring-data-ldap 传递地添加了 spring-repository.xsd,其中 spring-ldap.xsd 使用。因此,Spring LDAP 的 XML 配置支持即使在不使用 Spring Data 的功能集的情况下也需要依赖项。

spring-data-ldap transitively adds spring-repository.xsd, which spring-ldap.xsd uses. Because of this, Spring LDAP’s XML config support requires the dependency even when Spring Data’s feature set is not in use.

Getting Started

@"20" 提供了一些有用的示例,说明如何将 Spring LDAP 用于常见用例。

The samples provide some useful examples of how to use Spring LDAP for common use cases.

Support

如有问题,请在 @"22" 上提问。项目网页为 [role="bare"]@"23"。

If you have questions, ask them on Stack Overflow with the spring-ldap tag. The project web page is [role="bare"]https://spring.io/spring-ldap/.

Acknowledgements

启动 Spring LDAP 项目时的初期工作由 @"24" 赞助。项目的当前维护由 @"25" 资助,该公司已被 @"26" 收购。

The initial effort when starting the Spring LDAP project was sponsored by Jayway. Current maintenance of the project is funded by Pivotal, which has since been acquired by VMware.

感谢 @"27" 提供开源许可证,它在维护项目结构方面发挥了重要作用。

Thanks to Structure101 for providing an open source license that has come in handy for keeping the project structure in check.