簡介

概覽

Spring LDAP 旨在簡化 Java 中的 LDAP 程式設計。該庫提供的一些特性包括:

  • 對 LDAP 程式設計進行類似 JdbcTemplate 風格的模板簡化。

  • 類似 JPA 或 Hibernate 的基於註解的物件與目錄對映。

  • Spring Data repository 支援,包括對 QueryDSL 的支援。

  • 用於簡化構建 LDAP 查詢和辨別名(Distinguished Names)的工具。

  • 正確的 LDAP 連線池。

  • 客戶端 LDAP 補償事務支援。

傳統 Java LDAP 與 LdapClient 的比較

考慮一個方法,它應該在某個儲存中搜索所有人員並以列表形式返回他們的姓名。使用 JDBC,我們將建立一個連線並使用一個語句執行一個查詢。然後,我們將遍歷結果集並檢索我們想要的,將其新增到列表中。

使用 JNDI 操作 LDAP 資料庫時,我們將建立一個上下文並使用一個搜尋過濾器執行一次搜尋。然後,我們將遍歷生成的命名列舉,檢索我們想要的屬性,並將其新增到列表中。

在 Java LDAP 中實現此人員姓名搜尋方法的傳統方式如下所示。請注意標記為粗體的程式碼 - 這是實際執行與方法業務目的相關的任務的程式碼。其餘的是樣板程式碼(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://: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://: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 版本的新特性

雖然 Spring LDAP 2.0 版本對 API 進行了相當重要的現代化改進,但我們已盡最大努力確保向後相容性。使用 Spring LDAP 1.3.x 的程式碼,除少數例外,在使用 2.0 庫時無需修改即可編譯和執行。

例外情況是少數已移至新包的類,這是為了實現一些重要的重構。這些被移動的類通常不是預期公共 API 的一部分,遷移過程應該是平滑的。如果在升級後找不到 Spring LDAP 類,您應該在 IDE 中組織匯入。

不過,您應該會遇到一些棄用警告,並且還有許多其他的 API 改進。為了充分利用 2.0 版本,建議您放棄棄用的類和方法,遷移到新的、改進的 API 工具。

以下列表簡要描述了 Spring LDAP 2.0 中最重要的變化:

  • Spring LDAP 現在需要 Java 6。Spring 2.0 及更高版本仍然受支援。

  • 核心 API 已更新,支援 Java 5+ 的特性,例如泛型和可變引數。因此,整個 spring-ldap-tiger 模組已被棄用,我們鼓勵您遷移到使用核心 Spring LDAP 類。核心介面的引數化會在現有程式碼上引起大量編譯警告,我們鼓勵您採取適當措施消除這些警告。

  • ODM(物件-目錄對映)功能已移至核心模組,LdapOperationsLdapTemplate 中新增了一些方法,使用這種自動轉換來處理帶有 ODM 註解的類。有關更多資訊,請參閱物件-目錄對映 (ODM)

  • 現在(終於)提供了自定義 XML 名稱空間,以簡化 Spring LDAP 的配置。有關更多資訊,請參閱[配置]

  • Spring LDAP 現在提供對 Spring Data Repository 和 QueryDSL 的支援。有關更多資訊,請參閱Spring LDAP 儲存庫

  • DirContextAdapter 和 ODM 中,現在正確處理了作為屬性值的 Name 例項,特別是關於辨別名相等性。有關更多資訊,請參閱DirContextAdapter 和屬性值作為辨別名 以及 ODM 和屬性值作為辨別名

  • DistinguishedName 和相關類已被棄用,取而代之的是標準的 Java LdapName。有關在使用 LdapName 物件時該庫如何提供幫助的資訊,請參閱動態構建辨別名

  • 添加了 Fluent 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 提供了開源許可,這對於檢查專案結構非常有用。