Configuration

配置 Spring LDAP 的推荐方式是使用自定义 XML 配置命名空间。为了使其可用,您需要在 bean 文件中包含 Spring LDAP 命名空间声明,如下所示:

<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*">

ContextSource Configuration

ContextSource 是使用 <ldap:context-source> 标记定义的。最简单的可能的 context-source 声明要求您指定服务器 URL、用户名和密码,如下所示:

Example 1. Simplest possible context-source declaration
<ldap:context-source
    username="cn=Administrator"
    password="secret"
    url="ldap://localhost:389" />

前一个示例创建了具有默认值(见本段之后的表格)的 LdapContextSource,以及指定的 URL 和认证凭据。context-source 上的可配置属性如下(必需属性用 * 标记):

Table 1. ContextSource Configuration Attributes
Attribute Default Description

id

contextSource

已创建 bean 的 ID。

username

使用 LDAP 服务器进行身份验证时要使用的用户名(主体)。通常是管理员用户的识别名称(例如 cn=Administrator),但根据服务器和身份验证方法不同而可能有所不同。如果未明确配置 authentication-source-ref,则必需。

password

使用 LDAP 服务器进行身份验证时要使用的密码(凭据)。如果未明确配置 authentication-source-ref,则必需。

url *

要使用的 LDAP 服务器的 URL。URL 应采用以下格式:ldap://myserver.example.com:389。对于 SSL 访问,请使用 ldaps 协议和相应的端口——例如,ldaps://myserver.example.com:636。如果您想要故障转移功能,则可以指定多个 URL,并用逗号分隔(,)。

base

LdapUtils.emptyLdapName()

基本 DN。配置此属性后,提供给 LDAP 操作和从 LDAP 操作接收的所有识别名称都将与此 LDAP 路径相关。这会极大地简化针对 LDAP 树的工作。但是,有几种情况需要访问基本路径。有关详细信息,请参阅 Obtaining a Reference to the Base LDAP Path

anonymous-read-only

false

定义是否通过匿名(未经身份验证)上下文执行只读操作。请注意,将此参数设置为 true 并与补偿性事务支持结合起来使用不受支持,并会遭到拒绝。

referral

null

定义处理转介的策略,如 here所述。有效值为:* ignore* follow* throw

native-pooling

false

指定是否应使用本机 Java LDAP 连接池。考虑改为使用 Spring LDAP 连接池。如需了解更多信息,请参阅 Pooling Support

authentication-source-ref

A SimpleAuthenticationSource instance.

要使用的 `AuthenticationSource`实例的 ID(参见 Custom Principal and Credentials Management)。

authentication-strategy-ref

A SimpleDirContextAuthenticationStrategy instance.

要使用的 DirContextAuthenticationStrategy 实例的 ID(请参阅 xref:configuration.adoc#spring-ldap-custom-dircontext-authentication-processing[Custom DirContext 身份验证处理)。

base-env-props-ref

要随环境一起提供给在构建时发送到 DirContext 的自定义环境属性 Map 的引用。

DirContext Authentication

当创建 DirContext 实例以用于执行 LDAP 服务器上的操作时,这些上下文通常需要被认证。Spring LDAP 提供了多个选项来配置它。

此部分是指 ContextSource 的核心功能中的身份验证上下文,以构造 DirContext 实例以供 LdapClientLdapTemplate 使用。LDAP 通常仅用于用户身份验证,ContextSource 也可用于此目的。该过程在 User Authentication using Spring LDAP 中讨论。

默认情况下,为只读和读写操作创建已认证上下文。您应该在 context-source 元素上指定要用于认证的 LDAP 用户的 usernamepassword

如果 username 是 LDAP 用户的识别名称 (DN),则它必须是从 LDAP 树根起的用户的完整 DN,无论是否在 context-source 元素上指定了 base LDAP 路径。

有些 LDAP 服务器设置允许匿名只读访问。如果您想针对只读操作使用匿名上下文,请将 anonymous-read-only 属性设置为 true

Custom DirContext Authentication Processing

Spring LDAP 中使用的默认认证机制是 SIMPLE 认证。这意味着主体(如 username 属性所指定)和凭据(如 password 所指定)将在发送到 DirContext 实现构造函数的 Hashtable 中设置。

很多情况下,这个处理过程是不够的。例如,LDAP 服务器通常被设置为仅接受安全 TLS 通道上的通信。可能有必要使用特定的 LDAP 代理认证机制或其他关注点。

您可以通过向 context-source 元素提供 DirContextAuthenticationStrategy 实现引用来指定其他认证机制。若要这样做,请设置 authentication-strategy-ref 属性。

TLS

Spring LDAP 提供了针对要求 TLS 安全通道通信的 LDAP 服务器的两个不同的配置选项:DefaultTlsDirContextAuthenticationStrategyExternalTlsDirContextAuthenticationStrategy.这两个实现的协商目标连接上的 TLS 通道,但是它们在实际认证机制中不同。DefaultTlsDirContextAuthenticationStrategy 在安全通道上(通过使用指定的 usernamepassword)应用 SIMPLE 认证,而 ExternalTlsDirContextAuthenticationStrategy 使用外部 SASL 认证,应用由使用系统属性配置的客户端证书进行认证。

由于不同的 LDAP 服务器实现对 TLS 通道的显式关闭的响应不同(有些服务器需要平滑关闭连接,而其他服务器不支持),TLS DirContextAuthenticationStrategy 实现支持使用 shutdownTlsGracefully 参数指定关闭行为。如果这个属性被设置为 false(默认值),则不会发生显式 TLS 关闭。如果它是 true,Spring LDAP 会尝试在关闭目标上下文之前平滑关闭 TLS 通道。

使用 TLS 连接时,您需要确保原生 LDAP 池化功能(如使用 native-pooling 属性指定的那样)已关闭。如果将 shutdownTlsGracefully 设置为 false,这一点尤为重要。然而,由于 TLS 通道协商过程相当昂贵,您可以通过使用 Pooling Support 中描述的 Spring LDAP 池化支持获得极大的性能提升。

Custom Principal and Credentials Management

虽然用于创建已认证 Context 的用户名(即用户 DN)和密码默认情况下被静态定义(context-source 元素配置中定义的那些在 ContextSource 的整个生命周期中使用),但在某些情况下这不是所需的行为。一种常见情况是,在为该用户执行 LDAP 操作时,应该使用当前用户的身份主体和凭据。您可以通过向 context-source 元素提供 AuthenticationSource 实现的引用(使用 authentication-source-ref 元素),而不是显式指定 usernamepassword 来修改默认行为。每次要创建一个认证的 Context 时,ContextSource 都会查询 AuthenticationSource 身份主体和凭据。

如果你使用 Spring Security,可以通过使用 Spring Security 附带的 SpringSecurityAuthenticationSource 实例配置 ContextSource 来确保始终使用当前登录用户的负责人和凭证。以下示例展示了如何操作:

Example 2. Using the SpringSecurityAuthenticationSource
<beans>
...
    <ldap:context-source
        url="ldap://localhost:389"
        authentication-source-ref="springSecurityAuthenticationSource"/>

    <bean id="springSecurityAuthenticationSource"
        class="org.springframework.security.ldap.authentication.SpringSecurityAuthenticationSource" />
...
</beans>

在我们使用 AuthenticationSource 时,我们未为 usernamepassword 指定任何。当使用默认行为时才需要这些属性。

使用 SpringSecurityAuthenticationSource 时,您需要使用 Spring Security 的 LdapAuthenticationProvider 对用户进行 LDAP 认证。

Native Java LDAP Pooling

内部 Java LDAP 提供程序提供一些非常基本的连接池功能。你可以在 AbstractContextSource 中使用 pooled 标志来启用或禁用此 LDAP 连接池。默认值为 false(自版本 1.3 起)——即,Java 原生 LDAP 连接池已关闭。LDAP 连接池的配置通过使用 System 属性进行管理,因此你需要在 Spring 上下文配置外部手动处理此操作。你可以在 here 中找到本机连接池配置的详细信息。

原生 LDAP 连接池化存在几个严重的缺陷,这就是 Spring LDAP 提供一种更为复杂的方法进行 LDAP 连接池化的原因,如 Pooling Support 中所述。如果您需要池化功能,这是推荐的做法。

无论池配置如何,ContextSource#getContext(String principal, String credentials) 方法始终明确不使用本机 Java LDAP 池,以便密码重置尽快生效。

Advanced ContextSource Configuration

本节涵盖了更高级的 ContextSource 配置方式。

Custom DirContext Environment Properties

在某些情况下,除了直接在 context-source 中可配置的属性以外,您可能还想指定其他环境设置属性。您应该将此类属性设置在 Map 中,并在 base-env-props-ref 属性中引用它们。

LdapClient Configuration

LdapClient 是用于调用 LDAP 后端的全新接口。它通过以下方式改进了 LdapTemplate

  • Provides built-in Stream support

  • 提供了一个简化的 API,其中重点关注绑定 ©、搜索 ®、修改 (U)、解除绑定 (D) 和身份验证。

LdapClient 还不支持 ODM。如果您需要,LdapTemplate 具备此功能。如果需要,LdapClientLdapTemplate 能在同一应用程序中很好地共存。

使用 LdapClient#create 工厂方法可以定义一个 LdapClient,如下所示:

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

此元素引用默认的 ContextSource,预计其 ID 为 contextSourcecontext-source 元素的默认值)。

您的 LdapClient 实例可以配置为如何处理某些已检查异常以及查询应该使用哪些默认 SearchControls

LdapTemplate Configuration

LdapTemplate 通过使用 <ldap:ldap-template> 元素定义。最简单的可能的 ldap-template 声明是元素本身:

Example 4. Simplest possible ldap-template declaration
<ldap:ldap-template />

元素本身会创建一个 LdapTemplate 实例(ID 为默认值),引用默认的 ContextSource,预计其 ID 为 contextSourcecontext-source 元素的默认值)。

下表描述了 ldap-template 中的可配置属性:

Table 2. LdapTemplate Configuration Attributes
Attribute Default Description

id

ldapTemplate

已创建 bean 的 ID。

context-source-ref

contextSource

要使用的 ContextSource 实例的 ID。

count-limit

0

搜索的默认计数限制。0 表示无限制。

time-limit

0

搜索的默认时间限制(以毫秒为单位)。0 表示无限制。

search-scope

SUBTREE

搜索的默认搜索范围。有效值为:* OBJECT* ONELEVEL* SUBTREE

ignore-name-not-found

false

指定是否应在搜索中忽略 NameNotFoundException。将此属性设置为 true 使得由无效搜索基础导致的错误被默默接受。

ignore-partial-result

false

指定是否应在搜索中忽略 PartialResultException。一些 LDAP 服务器在引用方面存在问题。这些通常应自动遵循。但是,如果这不起作用,则它会表现为 PartialResultException。将此属性设置为 true 提供了此问题的解决方法。

odm-ref

要使用的 ObjectDirectoryMapper 实例的 ID。默认值是默认配置的 DefaultObjectDirectoryMapper

Obtaining a Reference to the Base LDAP Path

如前所述,您可以为 ContextSource 提供基础 LDAP 路径,指定所有操作相对的 LDAP 树根。这意味着您仅会在整个系统中使用相对可分辨名称,这通常非常方便。但是,在某些情况下,您可能需要访问基础路径才能构建相对于 LDAP 树实际根的全 DN。一个示例将在使用 LDAP 组(例如 groupOfNames 对象类)时遇到。在这种情况下,每个组成员属性值都需要是引用成员的全 DN。

正因为如此,Spring LDAP 有一种机制,通过该机制,任何受 Spring 控制的 Bean 都可以在启动时提供基础路径。为了让 Bean 被基础路径通知,需要实现两件事。首先,想要获取基础路径引用的 Bean 需要实现 BaseLdapNameAware 接口。其次,您需要在应用程序上下文中定义 BaseLdapPathBeanPostProcessor。以下示例演示了如何实现 BaseLdapNameAware

Example 5. Implementing BaseLdapNameAware
public class PersonService implements PersonService*, BaseLdapNameAware* {
   ...
   *private LdapName basePath;

   public void setBaseLdapPath(LdapName basePath) {
      this.basePath = basePath;
   }*
   ...
   private LdapName getFullPersonDn(Person person) {
      return LdapNameBuilder.newInstance(*basePath*)
          .add(person.getDn())
          .build();
   }
   ...
}

以下示例演示了如何定义 BaseLdapPathBeanPostProcessor

Example 6. Specifying a BaseLdapPathBeanPostProcessor in your ApplicationContext
<beans>
   ...
   <ldap:context-source
          username="cn=Administrator"
          password="secret"
          url="ldap://localhost:389"
          base="dc=261consulting,dc=com" />
   ...
   *<bean class="org.springframework.ldap.core.support.BaseLdapPathBeanPostProcessor" />*
</beans>

BaseLdapPathBeanPostProcessor 的默认行为是使用 ApplicationContext 中单个已定义 BaseLdapPathSource (AbstractContextSource) 的基础路径。如果定义了多个 BaseLdapPathSource,您需要通过设置 baseLdapPathSourceName 属性来指定要使用哪一个。