1-5章的翻譯見:http://www.reibang.com/p/77517e26a357
說明
該文檔根據官方英文文檔翻譯而來,該文檔是對spring-ldap-core的2.3.2.RELEASE版本的介紹。翻譯如下。
Spring LDAP 參考文檔
Mattias Hellborg Arthursson困介,Ulrik Sandberg,Eric Dalquist幽崩,Keith Barlow呼盆,Rob Winch。2.3.2.RELEASE版本盾剩。
Spring LDAP使得我們構建基于Spring的那些使用了LDAP協(xié)議的應用變得簡單
假如你不把本文檔設為收費閱讀雷激,甚至你在提供本文內容時在文檔中包含此版權說明,那你可以以紙質版或電子版的形式拷貝本文的副本來自己使用或做他用
6. 配置
6.1 前言
推薦配置Spring LDAP的方式是使用在XML中引入Spring LDAP配置的命名空間告私。我們需要將Spring
LDAP命名空間的聲明引入我們的bean文件中屎暇,例如:
<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 http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/ldap http://www.springframework.org/schema/ldap/spring-ldap.xsd">
6.2. 配置ContextSource
ContextSource 通過使用ldap:context-source標簽來配置。最簡單的context-source配置值需要我們提供服務器url驻粟,username以及password:
最簡單的context-source配置
<ldap:context-source
username="cn=Administrator"
password="secret"
url="ldap://localhost:389" />
這將會創(chuàng)建一個默認的LdapContextSource (參見下面的表格)以及指定的URL和身份驗證憑據根悼。context-source所有可配置的屬性如下表,其中帶*的是必需配置的屬性:
表1. ContextSource 的配置屬性
Attribute | Default | Description |
---|---|---|
id | contextSource | 被創(chuàng)建的bean的id |
username | 當驗證LDAP服務器的時候需要用到username蜀撑。一般是admin用戶的DN值(例如:cn=Administrator)挤巡,但是也可能會由于不同的服務器與認證方式而有差異。當authentication-source-ref沒有顯示的配置的時候酷麦,username是必需的 | |
password | 當驗證LDAP服務器的時候需要用到password矿卑。當authentication-source-ref沒有顯示的配置的時候,password是必需的 | |
url* | LDAP服務器的URL沃饶。URL應該是如下的格式:ldap://myserver.example.com:389 母廷。當使用SSL認證時瀑晒,使用ldaps協(xié)議與核實的端口,如:ldaps://myserver.example.com:636 徘意。如果需要故障轉移(fail-over)功能,可以配置多個URL轩褐,URL之間使用逗號“,”分隔 |
|
base | LdapUtils.emptyLdapName() | base DN椎咧。當該屬性配置之后,所有從LDAP中獲取的DN或增加到LDAP的DN都會根據該base DN來操作把介。這可以大大簡化針對LDAP樹的操作勤讽。然而仍然有在某些情況下你需要訪問base Path。想要知道關于這個的更多信息拗踢,請參閱Obtaining a reference to the base LDAP path |
anonymous-read-only | false | 用于定義一個匿名用戶(未登錄用戶)是否有只讀的操作權限脚牍。注意不支持將該配置設置為true的同時開啟事務補償。 |
referral | null | 定義處理referral的策略巢墅,這里有詳細的描述诸狭。允許的值有:ignore follow throw |
native-pooling | false | 指出本地Java LDAP連接池是否啟用。如果要使用Spring LDAP連接池君纫,請參閱Pooling Support |
authentication-source-ref | A SimpleAuthenticationSource instance | 要使用的AuthenticationSource 實例的id(詳情見下文) |
authentication-strategy-ref | A SimpleDirContextAuthenticationStrategy instance. | 要使用的SimpleDirContextAuthenticationStrategy 實例的id(詳情見下文) |
base-env-props-ref | 指向一個存儲環(huán)境屬性的一個map驯遇。這個map會在DirContext 構建是傳入。 |
6.2.1 認證DirContext
當DirContext 實例被創(chuàng)建后蓄髓,在LDAP服務器中進行操作的時候這些contexts需要進行認證叉庐。使用Spring LDAP配置時有許多不同的選項。
這部分引用了ContextSource 核心功能中的authenticating contexts会喝。LdapTemplate可以使用ContextSource來構造DirContext 實例來使用陡叠。LDAP通常僅僅用作用戶的驗證(
譯者注:如作為用戶的登錄驗證
),ContextSource 也可以用來做這個肢执。這一過程在User Authentication using Spring LDAP
中有詳細描述枉阵。
驗證過的contexts創(chuàng)建后默認擁有只讀和讀寫的操作。你可以在context-source基礎上獲取LDAP中的用戶的username 與 password 屬性來做用戶驗證的事情蔚万。
如果username是LDAP用戶的DN值岭妖,不管在context-source中是否指定了base屬性,username應該是從LDAP樹的根節(jié)點開始完整的DN值反璃。
某些LDAP服務器可以設置為匿名用戶可以擁有只讀的權限昵慌,如果你想使用匿名的Context來做只讀的操作,可以將配置 anonymous-read-only 設置為true淮蜈。
自定義DirContext認證處理(Custom DirContext Authentication Processing
)
翻譯略 大意是說默認的認證方式是SIMPLE
斋攀。該方式將username 與 password放入Hashtable傳給DirContext的構造器。然而有些LDAP服務器只允許安全的TLS通道的通信梧田,這可能就需要使用特定的LDAP代理機制(LDAP Proxy Auth )丧失,這就需要提供一個DirContextAuthenticationStrategy 的實現類,并在context-source中配置authentication-strategy-ref 屬性置森。
TLS
翻譯略 大意是說Spring LDAP針對TLS的認證策略提供了兩種方案DefaultTlsDirContextAuthenticationStrategy and ExternalTlsDirContextAuthenticationStrategy掂林。DefaultTlsDirContextAuthenticationStrategy 這個default開頭的方案就是在TLS安全通道內使用username 與password來簡單的認證,而external開頭的方案在TLS通道內使用EXTERNAL SASL 認證方式巷疼。第二段說了不同的服務器對通道的關閉方式的響應不同,有些要求優(yōu)雅的關閉(shutdown gracefully)。DirContextAuthenticationStrategy提供 了shutdownTlsGracefully 參數晌坤,如果為false (默認值)將會顯式的關閉TLS,若為true旦袋,則會在關閉context之前嘗試優(yōu)雅的關閉TLS骤菠。
Custom Principal and Credentials ManagementUsing the(標題不全讓我怎么翻譯-_-||)
翻譯略 大意是我們配置了username與password來創(chuàng)建了context后,就會一直使用這個用戶來操作疤孕。這在某些情況下很不方便或者不符合業(yè)務要求商乎。一個替代方案是在配置context-source時,將authentication-source-ref屬性配置為指向一個AuthenticationSource 的實現類祭阀。這樣每當Context 被創(chuàng)建時鹉戚,都會由ContextSource 調用AuthenticationSource 來獲取認證信息。
當使用Spring Security時专控,你可以將配置中的ContextSource 用SpringSecurityAuthenticationSource 來代替崩瓤,以便能夠保證使用用戶名密碼來認證當前登錄的用戶。
*使用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 時踩官,就無需在context-source中指定用戶名和密碼了却桶。
當使用SpringSecurityAuthenticationSource 時,你需要使用Spring Security的LdapAuthenticationProvider 來從LDAP中認證用戶蔗牡。
6.2.2. Java LDAP池
翻譯略 Java LDAP內置提供了一些基礎的連接池的能力颖系,可以在AbstractContextSource中的pooled 屬性中設置開關。自1.3版本后辩越,該屬性默認為false嘁扼,也就是說Java LDAP池默認關閉。LDAP連接池使用了System 屬性黔攒,并不在Spring Context configuration配置中趁啸,因此需要手動處理。詳情可以看這里
內置的LDAP連接池有許多缺點督惰,這既是為什么Spring LDAP要提供一個更精致的LDAP連接池技術不傅,如果你需要連接池的功能,我們推薦使用Spring LDAP的連接池技術赏胚,更多信息參閱Pooling Support
為了使重置密碼功能盡快生效访娶,無論連接池怎么配置,ContextSource#getContext(String principal, String credentials)方法將不會使用Java LDAP連接池觉阅。
6.2.3. 高級ContextSource 配置
自定義DirContext 環(huán)境參數
在某些情況下用戶可能需要在context-source中指定除默認配置外的額外的啟動環(huán)境參數崖疤。這些屬性可以放入到map中并被base-env-props-ref參數引用秘车。
6.3. LdapTemplate 配置
翻譯略
6.4. 獲取base LDAP path
就像上文說說的,ContextSource可以獲得一個base Path來指定所有操作的相對路徑劫哼。這意味著你只能在系統(tǒng)中使用相對DN來操作叮趴,這當然相當方便。然而权烧,在某些情況下疫向,你可能需要獲取到base Path的值來組裝一個從LDAP 根節(jié)點開始的絕對DN值。一個直觀的例子就是:當我們操作LDAP群組時豪嚎,群組中的member屬性值必須是指向某entry的絕對DN值。
由于以上原因谈火,Spring LDAP提供了一個機制:任何Spring控制的bean都可以在啟動時獲取到base Path侈询。對于bean來說要獲取base Path,有兩點要注意:第一糯耍,想要獲取base Path的bean必須實現BaseLdapNameAware 接口扔字。第二,需要在application context中定義BaseLdapPathBeanPostProcessor温技。
實現BaseLdapNameAware 接口
package com.example.service;
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();
}
...
}
*在ApplicationContext中指定BaseLdapPathBeanPostProcessor *
<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)中獲取base Path革为。如果有不止一個BaseLdapPathSource 被定義,那你需要指定baseLdapPathSourceName 屬性來使用特定的BaseLdapPathSource 舵鳞。
7. Spring LDAP Repositories
7.1. 前言
Spring LDAP內置了對Spring Data repositories的支持震檩。基本的功能與配置在 這里蜓堕。當你使用該功能時抛虏,注意一下幾點:
- Spring LDAP repositories可以在你的XML配置文件中使用ldap:repositories標簽來配置,也可以使用@EnableLdapRepositories注解一個配置類達到相同的目的套才。
- 為了支持將LdapQuery 的參數自動轉換成對應的repositories資源迂猴,你需要實現LdapRepository 接口而不是CrudRepository接口。
- 所有的Spring LDAP repositories都要與被注解的entry類配合使用背伴,詳情參閱 Object-Directory Mapping (ODM)
- 因為所有ODM管理的類都有DN作為ID沸毁。因此所有的Spring LDAP repositories必須有一個類型為javax.naming.Name的ID參數。事實上傻寂,內置的LdapRepository 只使用一個參數息尺,那就是托管的實體類(被ODM注解的類),默認為javax.naming.Name類型的ID疾掰。
- 由于LDAP協(xié)議的原因掷倔,Spring LDAP repositories不支持分頁與排序。
7.2. QueryDSL 支持
Spring LDAP包含了基本的QueryDSL 的支持个绍。該支持包含以下部分:
- LdapAnnotationProcessor勒葱,一個注解處理器浪汪,用于在Spring LDAP ODM 注解的基礎上生成QueryDSL 。更多ODM注解的信息請參考 Object-Directory Mapping (ODM)凛虽。
- QueryDslLdapQuery死遭,一個查詢實現類,用于構建與執(zhí)行QueryDSL 的查詢凯旋。
- Spring Data repository支持QueryDSL 斷言呀潭。QueryDslPredicateExecutor 包括一些額外的方法。繼承QueryDslPredicateExecutor接口 與LdapRepository 來將QueryDSL 斷言支持包括到你的repository中至非。
8. 連接池支持
8.1. 前言
LDAP 連接池幫助減少每次LDAP交互式都要創(chuàng)建LDAP 連接的開銷钠署。而Java LDAP pooling support在配置選項與特性上存在自身的限制,如連接驗證與連接池的維護荒椭。Spring LDAP在每個ContextSource 基礎上都提供了更詳細的配置項谐鼎。
在application context 中的<ldap:context-source />元素下的<ldap:pooling />子元素可以對連接池進行配置。
譯者注:下面的句子標點符號混亂趣惠,無法正確理解與翻譯狸棍,原文如下:
Read-only and read-write DirContext objects are pooled separately (if anonymous-read-only is specified.Jakarta Commons-Pool is used to provide the underlying pool implementation.
沒錯,就是有個單括號味悄。
8.2. DirContext 驗證
比起JDK提供的LDAP連接池功能草戈,使用自定義連接池技術的關鍵動機就是對池連接的驗證。驗證機制能夠保證無論是把DirContext 從連接池取出還是放入連接池甚至是在連接池中處于空閑狀態(tài)侍瑟,DirContext 連接都會被檢查并確保仍然保持連接與良好的配置唐片。
當連接驗證被正確配置后,池中共用的連接都會使用DefaultDirContextValidator來進行驗證涨颜。DefaultDirContextValidator 會執(zhí)行DirContext.search(String, String, SearchControls)操作牵触,其中第一個參數為空,第二個參數為objectclass=*的過濾器咐低,第三個參數為SearchControls 揽思,該參數被設置為返回objectClass屬性并且超時設置為500ms。如果返回了NamingEnumeration 见擦,則證明DirContext 通過了驗證钉汗,反之如果沒有返回值或者拋出異常,則證明DirContext 沒有通過驗證鲤屡。對于大多數的LDAP服務器來說只需要使用默認配置即可损痰,無需任何修改即可正常工作并提供最快的方式來驗證DirContext 。如果需要自定義酒来,下面的配置屬性可以進行自定義配置卢未。
8.3. 連接池的配置
翻譯略 表格
8.4. Pool2 配置
翻譯略 表格
8.5. 配置
翻譯略 xml文件
8.5.1. 對驗證操作的配置
翻譯略 xml文件 可以看出就是在取出與空閑時都要對池中的連接對象進行驗證。
8.6. 已知問題
8.6.1. 自定義認證
PoolingContextSource 會假定由ContextSource.getReadOnlyContext()獲取的所有DirContext 對象都具有相同的環(huán)境,同樣的辽社,所有由ContextSource.getReadWriteContext()獲取的DirContext 也是具有相同的環(huán)境伟墙。這就意味著在PoolingContextSource 中使用AuthenticationSource 將LdapContextSource 的配置包裹起來可能并不會產生我們預期的功能。(譯者注:在上面的情況下滴铅,我們預期的是每次驗證都從AuthenticationSource 中取認證戳葵,而無需配置username 與password了)。這樣連接池每次都只會使用第一個用戶的憑據汉匙,除非使用新的連接拱烁,否則,之后的上下文環(huán)境中的所有請求在該請求線程中噩翠,都不會被AuthenticationSource 中指定的用戶來填充(驗證)戏自。
9. 添加API中沒有的重載方法
9.1. 自定義search方法的實現
翻譯略 沒什么好說的,大意是雖然在API中有很多重載的方法能夠保證大家不同的要求伤锚,但是還是會有一些特定的要求需要自定義一個方法擅笔,這里它提供了一個接口---SearchExecutor。然后又提供了一個CollectingNameClassPairCallbackHandler類见芹,來處理自定義search后返回的數據,最后將這兩個作為參數傳入 ldapTemplate.search(executor, handler)方法中蠢涝。
9.2. 實現其他自定義的Context方法
翻譯略 類似的有一個ContextExecutor 接口玄呛,實現其方法executeWithContext即可。該方法可以對DirContext做一些自定義的操作和二,然后通過ldapTemplate.executeReadOnly(executor)來或ldapTemplate.executeReadWrite(executor)調用徘铝。
10. 處理DirContext
10.1. 自定義DirContext處理前后的操作
翻譯略 這個接口DirContextProcessor實現其方法以便在search操作執(zhí)行前或執(zhí)行后做相應的操作。
10.2. 實現一個 Request Control DirContextProcessor
翻譯略
10.3. 搜索結果分頁
一些查詢會返回大量的數據惯吕。如果很難通過過濾器將其拆分成更小的數據塊惕它,那我們就希望每次查詢時只返回一部分數據。這就是我們常說的分頁查詢結果废登。每一頁的結果都能被展示出來并且能夠鏈接到上一頁與下一頁淹魄。如果沒有這個功能的話,客戶端只能手動的限制返回到頁面的結果堡距,或者獲取所有的結果并把它分成合適的數量展示到頁面中甲锡。前者相當復雜,而后者會消耗不必要的內存空間羽戒。
某些LDAPserver提供了對PagedResultsControl的支持缤沦,PagedResultsControl要求LDAP服務器通過search操作返回的結果是按特定大小分頁的。用戶通過search方法中的參數簡單的控制返回哪一頁數據易稠。但是用戶必須跟蹤兩次方法調用之間的cookie缸废。服務器使用這個cookie來跟蹤上次分頁請求時返回結果后的位置,以便從該位置繼續(xù)搜索返回下一頁的結果。
Spring LDAP是通過改變上文中討論過的LdapContext的pre- and postprocessing預處理與后處理方法來實現分頁結果支持的企量。它使用PagedResultsDirContextProcessor來進行處理测萎。PagedResultsDirContextProcessor 根據請求的頁的參數創(chuàng)建一個PagedResultsControl對象,并將其加入到LdapContext中梁钾。查詢之后會得到PagedResultsResponseControl 并獲取分頁的cookie绳泉,該cookie能夠將context保持在連續(xù)的分頁請求之間。
下面的例子展示了如何使用PagedResultsDirContextProcessor的分頁查詢功能:
使用PagedResultsDirContextProcessor進行分頁查詢
public List<String> getAllPersonNames() {
final SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
final PagedResultsDirContextProcessor processor =
new PagedResultsDirContextProcessor(PAGE_SIZE);
return SingleContextSource.doWithSingleContext(
contextSource, new LdapOperationsCallback<List<String>>() {
@Override
public List<String> doWithLdapOperations(LdapOperations operations) {
List<String> result = new LinkedList<String>();
do {
List<String> oneResult = operations.search(
"ou=People",
"(&(objectclass=person))",
searchControls,
CN_ATTRIBUTES_MAPPER,
processor);
result.addAll(oneResult);
} while(processor.hasMore());
return result;
}
});
}
為保證分頁cookie能繼續(xù)從分頁出進行查詢姆泻,這要求使用同一個連接來進行查詢零酪。正如上面展示的那樣,這一過程可以讓SingleContextSource來完成拇勃。