官網:http://www.springframework.org/ldap
官方文檔及例子(重要):http://docs.spring.io/spring-ldap/docs/2.1.0.RELEASE/reference/
JAVA文檔(重要):http://docs.spring.io/spring-ldap/docs/2.1.0.RELEASE/apidocs/
GitHub(大量例子):https://github.com/spring-projects/spring-ldap
Spring LDAP Reference
2.基本使用
2.1 使用AttributesMapper進行search和lookup
(1)通過search返回一個屬性值
1 import static org.springframework.ldap.query.LdapQueryBuilder.query; 2 3 public class PersonRepoImpl implements PersonRepo{ 4 private LdapTemplate ldapTemplate; 5 6 public void setLdapTemplate(LdapTemplate ldapTemplate){ 7 this.ldapTemplate = ldapTemplate; 8 } 9 10 public List<String> getAllPersonNames(){ 11 return ldapTemplate.search({ 12 query().where("objectclass").is("person"), 13 new AttributeMapper<String>(){ 14 public String mapFromAttributes(Attribute attrs)throws NamingException{ 15 return (String) attrs.get("cn").get(); 16 } 17 } 18 } 19 }); 20 } 21 }
(2)通過search返回一個Person對象
1 package com.example.repo; 2 import static org.springframework.ldap.query.LdapQueryBuilder.query; 3 4 public class PersonRepoImpl implements PersonRepo { 5 private LdapTemplate ldapTemplate; 6 ... 7 private class PersonAttributesMapper implements AttributesMapper<Person> { 8 public Person mapFromAttributes(Attributes attrs) throws NamingException { 9 Person person = new Person(); 10 person.setFullName((String)attrs.get("cn").get()); 11 person.setLastName((String)attrs.get("sn").get()); 12 person.setDescription((String)attrs.get("description").get()); 13 return person; 14 } 15 } 16 17 public List<Person> getAllPersons() { 18 return ldapTemplate.search(query() 19 .where("objectclass").is("person"), new PersonAttributesMapper()); 20 } 21 }
(3)通過lookup返回一個Person對象
在ldap中,有兩個"查詢"概念,search和lookup。search是ldaptemplate對每一個entry進行查詢,lookup是通過DN直接找到某個條目。
"Entries in LDAP are uniquely identified by their distinguished name (DN). If you have the DN of an entry, you can retrieve(找回) the entry directly without searching for it. This is called a lookup in Java LDAP."
在下面的lookup代碼中,ldap會跳過為AttributesMapper查找屬性。
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 private LdapTemplate ldapTemplate; 5 ... 6 public Person findPerson(String dn) { 7 return ldapTemplate.lookup(dn, new PersonAttributesMapper()); 8 } 9 }
2.2 創建LDAP Queries
ldap的search 包含許多參數,比如:
1 Base LDAP path 基本路徑(search應該從LDAP樹的哪里開始) 2 Search scope 查詢范圍(search應該進行到LDAP樹的哪一層) 3 returned attributes要返回的屬性 4 Search filter 查詢過濾器
1 package com.example.repo; 2 import static org.springframework.ldap.query.LdapQueryBuilder.query; 3 4 public class PersonRepoImpl implements PersonRepo { 5 private LdapTemplate ldapTemplate; 6 ... 7 public List<String> getPersonNamesByLastName(String lastName) { 8 9 LdapQuery query = query() 10 .base("dc=261consulting,dc=com") 11 .attributes("cn", "sn") //返回的屬性 12 .where("objectclass").is("person") 13 .and("sn").is(lastName); 14 15 return ldapTemplate.search(query, new AttributesMapper<String>() { 17 public String mapFromAttributes(Attributes attrs)throws NamingException { 20 return attrs.get("cn").get(); //查詢每一個entry的"cn"值 21 } 22 }); 23 } 24 }
2.3 動態創建 Distinguished Names(DN)
為了簡化對DN的使用,spring-ldap提供了LdapNameBuilder,和工具類LdapUtils。
假設一個Person有如下的屬性:
1 Attribute Name Attribute Value 2 country Sweden 3 company Some Company 4 fullname Some Person
(1)使用 LdapNameBuilder 動態創建 LdapName
1 package com.example.repo; 2 import org.springframework.ldap.support.LdapNameBuilder; 3 import javax.naming.Name; 4 5 public class PersonRepoImpl implements PersonRepo { 6 public static final String BASE_DN = "dc=example,dc=com"; 7 8 protected Name buildDn(Person p) { 9 return LdapNameBuilder.newInstance(BASE_DN) 10 .add("c", p.getCountry()) 11 .add("ou", p.getCompany()) 12 .add("cn", p.getFullname()) 13 .build(); 14 } 15 ...
(2)用 LdapUtils 獲取屬性值
1 package com.example.repo; 2 import org.springframework.ldap.support.LdapNameBuilder; 3 import javax.naming.Name; 4 public class PersonRepoImpl implements PersonRepo { 5 ... 6 protected Person buildPerson(Name dn, Attributes attrs) { 7 Person person = new Person(); 8 person.setCountry(LdapUtils.getStringValue(dn, "c")); 9 person.setCompany(LdapUtils.getStringValue(dn, "ou")); 10 person.setFullname(LdapUtils.getStringValue(dn, "cn")); 11 // Populate rest of person object using attributes. 12 13 return person; 14 }
2.4 綁定和解綁
在Ldap中,新增與刪除叫做綁定和解綁。
2.4.1 新增數據
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 private LdapTemplate ldapTemplate; 5 ... 6 public void create(Person p) { 7 Name dn = buildDn(p); 8 ldapTemplate.bind(dn, null, buildAttributes(p)); 9 } 10 11 private Attributes buildAttributes(Person p) { 12 Attributes attrs = new BasicAttributes(); 13 BasicAttribute ocattr = new BasicAttribute("objectclass"); 14 ocattr.add("top"); 15 ocattr.add("person"); 16 attrs.put(ocattr); 17 attrs.put("cn", "Some Person"); 18 attrs.put("sn", "Person"); 19 return attrs; 20 } 21 }
2.4.2 刪除數據
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 private LdapTemplate ldapTemplate; 5 ... 6 public void delete(Person p) { 7 Name dn = buildDn(p); 8 ldapTemplate.unbind(dn); 9 } 10 }
2.4.3 更新數據
(1)使用 rebind 更新數據
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 private LdapTemplate ldapTemplate; 5 ... 6 public void update(Person p) { 7 Name dn = buildDn(p); 8 ldapTemplate.rebind(dn, null, buildAttributes(p)); 9 } 10 }
(2)使用 modifyAttributes 更新數據
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 private LdapTemplate ldapTemplate; 5 ... 6 public void updateDescription(Person p) { 7 Name dn = buildDn(p); 8 Attribute attr = new BasicAttribute("description", p.getDescription()) 9 ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr); 10 ldapTemplate.modifyAttributes(dn, new ModificationItem[] {item}); 11 } 12 }
3.簡化 Attribute 的獲取和 DirContextAdapter 的操作
3.1 介紹
Java LDAP API 可以注冊一個DirContextAdapter來自動創建對象。spring-ldap使用了這個特點,在search和lookup中返回DirContextAdapter實例。
3.2 通過ContextMapper來search 和lookup
任何時候,想要在LDAP數據樹中查找entry,spring-ldap都會使用這個entry的DN和Attributes來構建一個DirContextAdapter,這使得我們不再需要使用 AttributesMapper,而是使用ContextMapper來對獲取的屬性值進行轉換。
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 ... 5 private static class PersonContextMapper implements ContextMapper { 6 public Object mapFromContext(Object ctx) { 7 DirContextAdapter context = (DirContextAdapter)ctx; 8 Person p = new Person(); 9 p.setFullName(context.getStringAttribute("cn")); 10 p.setLastName(context.getStringAttribute("sn")); 11 p.setDescription(context.getStringAttribute("description")); 12 return p; 13 } 14 } 15 16 public Person findByPrimaryKey(String name, String company, String country) { 18 Name dn = buildDn(name, company, country); 19 return ldapTemplate.lookup(dn, new PersonContextMapper()); 20 } 21 }
這里特別方便的一點是:當屬性具有多值時,可以通過getStringAttributes()來獲取。
1 private static class PersonContextMapper implements ContextMapper { 2 public Object mapFromContext(Object ctx) { 3 DirContextAdapter context = (DirContextAdapter)ctx; 4 Person p = new Person(); 5 p.setFullName(context.getStringAttribute("cn")); 6 p.setLastName(context.getStringAttribute("sn")); 7 p.setDescription(context.getStringAttribute("description")); 8 // The roleNames property of Person is an String array 9 p.setRoleNames(context.getStringAttributes("roleNames")); 10 return p; 11 } 12 }
3.2.1 AbstactContextMapper
spring-ldap提供了一個ContextMapper的抽象的基礎實現類:AbstractContextMapper。自定義的的PersonContextMapper可以這樣寫:
1 private static class PersonContextMapper extends AbstractContextMapper { 2 public Object doMapFromContext(DirContextOperations ctx) { //ctx沒有用到?? 3 Person p = new Person(); 4 p.setFullName(context.getStringAttribute("cn")); 5 p.setLastName(context.getStringAttribute("sn")); 6 p.setDescription(context.getStringAttribute("description")); 7 return p; 8 } 9 }
3.3 使用DirContextAdapter新增和更新數據
注意新增的時候用的是:DirContextAdapter。更新的時候用的是:DirContextOperations。二者的關系:DirContextAdapter實現了DirContextOperations接口。
3.3.1 新增數據
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 ... 5 public void create(Person p) { 6 Name dn = buildDn(p); 7 DirContextAdapter context = new DirContextAdapter(dn); 8 //和獲取一樣,set也可以有多值 9 context.setAttributeValues("objectclass", new String[] {"top", "person"}); 10 context.setAttributeValue("cn", p.getFullname()); 11 context.setAttributeValue("sn", p.getLastname()); 12 context.setAttributeValue("description", p.getDescription()); 13 14 ldapTemplate.bind(context); 15 } 16 }
3.3.2 更新數據
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 ... 5 public void update(Person p) { 6 Name dn = buildDn(p); 7 DirContextOperations context = ldapTemplate.lookupContext(dn); 8 9 context.setAttributeValue("cn", p.getFullname()); 10 context.setAttributeValue("sn", p.getLastname()); 11 context.setAttributeValue("description", p.getDescription()); 12 13 ldapTemplate.modifyAttributes(context); 14 } 15 }
3.3.3 合並新增和更新數據的代碼
從前面兩段代碼可知,新增和更新有重復的代碼,因此合並重復代碼,整理如下:
1 package com.example.repo; 2 3 public class PersonRepoImpl implements PersonRepo { 4 private LdapTemplate ldapTemplate; 5 6 ... 7 public void create(Person p) { 8 Name dn = buildDn(p); 9 DirContextAdapter context = new DirContextAdapter(dn); 11 context.setAttributeValues("objectclass", new String[] {"top", "person"}); 12 mapToContext(p, context); 13 ldapTemplate.bind(context); 14 } 15 16 public void update(Person p) { 17 Name dn = buildDn(p); 18 DirContextOperations context = ldapTemplate.lookupContext(dn); 19 mapToContext(person, context); 20 ldapTemplate.modifyAttributes(context); 21 } 22 23 protected void mapToContext (Person p, DirContextOperations context) { 24 context.setAttributeValue("cn", p.getFullName()); 25 context.setAttributeValue("sn", p.getLastName()); 26 context.setAttributeValue("description", p.getDescription()); 27 } 28 }
3.4 DirContextAdapter和作為屬性值的DN
When managing security groups in LDAP it is very common to have attribute values that represent distinguished names. Since distinguished name equality differs from String equality (例如,空格和大小寫在DN的判等中是無視的), calculating attribute modifications using string equality will not work as expected.
假設一個member屬性值為:cn=John Doe,ou=People。如果代碼寫作如下,會被認為是兩個值,實際上它代表了同一個DN。
1 ctx.addAttributeValue("member", "CN=John Doe, OU=People")
要寫作如下:
1 ctx.addAttributeValue("member", LdapUtils.newLdapName("CN=John Doe, OU=People"))
使用DirContextAdapter來修改group membership:
1 public class GroupRepo implements BaseLdapNameAware { 2 private LdapTemplate ldapTemplate; 3 private LdapName baseLdapPath; 4 5 public void setLdapTemplate(LdapTemplate ldapTemplate) { 6 this.ldapTemplate = ldapTemplate; 7 } 8 9 public void setBaseLdapPath(LdapName baseLdapPath) { 10 this.setBaseLdapPath(baseLdapPath); 11 } 12 13 public void addMemberToGroup(String groupName, Person p) { 14 Name groupDn = buildGroupDn(groupName); 15 Name userDn = buildPersonDn(person.getFullname(),person.getCompany(), person.getCountry()); 19 20 DirContextOperation ctx = ldapTemplate.lookupContext(groupDn); 21 ctx.addAttributeValue("member", userDn); 22 23 ldapTemplate.update(ctx); 24 } 25 26 public void removeMemberFromGroup(String groupName, Person p) { 27 Name groupDn = buildGroupDn(String groupName); 28 Name userDn = buildPersonDn(person.getFullname(),person.getCompany(),person.getCountry()); 32 33 DirContextOperation ctx = ldapTemplate.lookupContext(groupDn); 34 ctx.removeAttributeValue("member", userDn); 35 36 ldapTemplate.update(ctx); 37 } 38 39 private Name buildGroupDn(String groupName) { 40 return LdapNameBuilder.newInstance("ou=Groups").add("cn", groupName).build(); 42 } 43 44 private Name buildPersonDn(String fullname, String company, String country) { 45 return LdapNameBuilder.newInstance(baseLdapPath).add("c", country).add("ou", company).add("cn", fullname).build(); 50 } 51 }
3.5 使用spring-ldap和DirContextAdapter的完整代碼
1 package com.example.repo; 2 import java.util.List; 3 4 import javax.naming.Name; 5 import javax.naming.NamingException; 6 import javax.naming.directory.Attributes; 7 import javax.naming.ldap.LdapName; 8 9 import org.springframework.ldap.core.AttributesMapper; 10 import org.springframework.ldap.core.ContextMapper; 11 import org.springframework.ldap.core.LdapTemplate; 12 import org.springframework.ldap.core.DirContextAdapter; 13 import org.springframework.ldap.filter.AndFilter; 14 import org.springframework.ldap.filter.EqualsFilter; 15 import org.springframework.ldap.filter.WhitespaceWildcardsFilter; 16 17 import static org.springframework.ldap.query.LdapQueryBuilder.query; 18 19 public class PersonRepoImpl implements PersonRepo { 20 private LdapTemplate ldapTemplate; 21 22 public void setLdapTemplate(LdapTemplate ldapTemplate) { 23 this.ldapTemplate = ldapTemplate; 24 } 25 26 public void create(Person person) { 27 DirContextAdapter context = new DirContextAdapter(buildDn(person)); 28 mapToContext(person, context); 29 ldapTemplate.bind(context); 30 } 31 32 public void update(Person person) { 33 Name dn = buildDn(person); 34 DirContextOperations context = ldapTemplate.lookupContext(dn); 35 mapToContext(person, context); 36 ldapTemplate.modifyAttributes(context); 37 } 38 39 public void delete(Person person) { 40 ldapTemplate.unbind(buildDn(person)); 41 } 42 43 public Person findByPrimaryKey(String name, String company, String country) { 44 Name dn = buildDn(name, company, country); 45 return ldapTemplate.lookup(dn, getContextMapper()); 46 } 47 48 public List findByName(String name) { 49 LdapQuery query = query() 50 .where("objectclass").is("person") 51 .and("cn").whitespaceWildcardsLike("name"); 52 53 return ldapTemplate.search(query, getContextMapper()); 54 } 55 56 public List findAll() { 57 EqualsFilter filter = new EqualsFilter("objectclass", "person"); 58 return ldapTemplate.search(LdapUtils.emptyPath(), filter.encode(), getContextMapper()); 59 } 60 61 protected ContextMapper getContextMapper() { 62 return new PersonContextMapper(); 63 } 64 65 protected Name buildDn(Person person) { 66 return buildDn(person.getFullname(), person.getCompany(), person.getCountry()); 67 } 68 69 protected Name buildDn(String fullname, String company, String country) { 70 return LdapNameBuilder.newInstance() 71 .add("c", country) 72 .add("ou", company) 73 .add("cn", fullname) 74 .build(); 75 } 76 77 protected void mapToContext(Person person, DirContextOperations context) { 78 context.setAttributeValues("objectclass", new String[] {"top", "person"}); 79 context.setAttributeValue("cn", person.getFullName()); 80 context.setAttributeValue("sn", person.getLastName()); 81 context.setAttributeValue("description", person.getDescription()); 82 } 83 84 private static class PersonContextMapper extends AbstractContextMapper<Person> { 85 public Person doMapFromContext(DirContextOperations context) { 86 Person person = new Person(); 87 person.setFullName(context.getStringAttribute("cn")); 88 person.setLastName(context.getStringAttribute("sn")); 89 person.setDescription(context.getStringAttribute("description")); 90 return person; 91 } 92 } 93 }
4. ODM(Object-Directory Mapping)
4.1 介紹
對象-關系映射框架比如Hibernate和JPA,都可以使用注解來將數據庫的表關系映射成java的對象。spring-ldap也提供類似的功能。
LdapPerations里有這些方法:
1 <T> T findByDn(Name dn, Class<T> clazz) 2 <T> T findOne(LdapQuery query, Class<T> clazz) 3 <T> List<T> find(LdapQuery query, Class<T> clazz) 4 <T> List<T> findAll(Class<T> clazz) 5 <T> List<T> findAll(Name base, SearchControls searchControls, Class<T> clazz) 6 <T> List<T> findAll(Name base, Filter filter, SearchControls searchControls, Class<T> clazz) 7 8 void create(Object entry) 9 void update(Object entry) 10 void delete(Object entry)
4.2 注解
每個注解的含義暫時先不詳細解釋。//todo
1 @Entry (required) 2 @Id (required) 3 @Attribute 4 @DnAttribute 5 @Transient
4.3 執行
1 @Entry(objectClasses = { "person", "top" }, base="ou=someOu") 2 public class Person { 3 @Id 4 private Name dn; 5 6 @Attribute(name="cn") 7 @DnAttribute(value="cn", index=1) 8 private String fullName; 9 10 // No @Attribute annotation means this will be bound to the LDAP attribute with the same value 12 private String description; 13 14 @DnAttribute(value="ou", index=0) 15 @Transient 16 private String company; 17 18 @Transient 19 private String someUnmappedField; 20 // ...more attributes below 21 }
24 public class OdmPersonRepo { 25 @Autowired 26 private LdapTemplate ldapTemplate; 27 28 public Person create(Person person) { 29 ldapTemplate.create(person); 30 return person; 31 } 32 33 public Person findByUid(String uid) { 34 return ldapTemplate.findOne(query().where("uid").is(uid), Person.class); 35 } 36 37 public void update(Person person) { 38 ldapTemplate.update(person); 39 } 40 41 public void delete(Person person) { 42 ldapTemplate.delete(person); 43 } 44 45 public List<Person> findAll() { 46 return ldapTemplate.findAll(Person.class); 47 } 48 49 public List<Person> findByLastName(String lastName) { 50 return ldapTemplate.find(query().where("sn").is(lastName), Person.class); 51 } 52 }
4.4 ODM和作為屬性值的DN
ldap中的安全組通常包含多值屬性,每一個屬性值都是一個user的DN。這些屬性值的處理在前面的 3.4 DirContextAdapter和作為屬性值的DN 中提到過。ODM同樣有簡單的處理辦法。
1 @Entry(objectClasses = {"top", "groupOfUniqueNames"}, base = "cn=groups") 2 public class Group { 3 4 @Id 5 private Name dn; 6 7 @Attribute(name="cn") 8 @DnAttribute("cn") 9 private String name; 10 11 @Attribute(name="uniqueMember") 12 private Set<Name> members; 13 14 public Name getDn() {return dn;} 18 public void setDn(Name dn) {this.dn = dn;} 21 22 public Set<Name> getMembers() {return members;} 26 public void setMembers(Set<Name> members) {this.members = members;} 29 30 public String getName() { return name;} 34 public void setName(String name) {this.name = name;} 37 38 public void addMember(Name member) {members.add(member);} 42 public void removeMember(Name member) {members.remove(member);} 45 }
5.高級LDAP Queries
//todo 暫略。
6.配置
6.1 介紹
采用xml文件方式配置時,需要加入如下xml的命名空間。
1 <beans xmlns="http://www.springframework.org/schema/beans" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns:ldap="http://www.springframework.org/schema/ldap" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans
5 http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://www.springframework.org/schema/ldap
7 http://www.springframework.org/schema/ldap/spring-ldap.xsd">
6.2 ContextSource 配置
最簡單的配置至少需要:username,password,url。完整的屬性參看官方文檔的說明。
1 <ldap:context-source 2 username="cn=Administrator" 3 password="secret" 4 url="ldap://localhost:389" />
6.2.1 DirContextAuthentication
創建並使用DirContext實例時,通常需要認證這些contexts,有不同的配置方式可供選擇。
在這一節里(12. User Authentication using Spring LDAP)討論了使用spring ldap進行用戶驗證。
authenticated contexts可以默認創建為read-only和read-write兩種。在context-source的配置中指定username和password。如果username是一個LDAP 用戶的dn,那么不管在context-source中是否配置了base LDAP path,這個user的DN也必須是username。(沒看懂)
有些LDAP服務器支持匿名read-only訪問。如果需要支持這個功能,將屬性anonymous-read-only設置為true即可。
(1)自定義DirContext的認證過程
spring ldap中的默認認證策略是簡單的。它將principal(這里是username)和credentials(這里是password)放在哈希表里傳遞給DirContext的構造函數。這通常是不夠的。因此可以在context-source里配置 authentication-strategy-ref,來指定自定義策略。
(2)使用SpringSecurityAuthenticationSource我們前面的配置,直接將username和password寫死了。但是一個更常見的場景是,當為某個用戶執行LDAP操作時,應該使用的是當前用戶的principals和credentials,而不是顯式指定。這可以通過配置SpringSecurityAuthenticationSource實現動態配置。
1 <beans> 2 ... 3 <ldap:context-source 4 url="ldap://localhost:389" 5 authentication-source-ref="springSecurityAuthenticationSource/> 6 7 <bean id="springSecurityAuthenticationSource"
class="org.springframework.security.ldap.authentication.SpringSecurityAuthenticationSource" /> 8 ... 9 </beans>
6.2.2 本地java LDAP Pooling//todo
6.2.3 高級ContextSource配置//todo
6.3 LdapTemplate Configuration
1 <ldap:ldap-template />
可供配置的屬性有:
| 屬性 | 默認值 | 說明 |
| id | ldapTemplate | |
| context-source-ref | contextSource | 使用的contextSource |
| count-limit | 0 | search的默認個數限制,0指的是沒有限制。 |
| time-limit | 0 | search的默認時間限制,0指的是沒有限制。 |
| search-scope | SUBTREE | 可選值有:OBJECT,ONELEVEL,SUBTREE |
| ignore-name-not-found | false | 指明search時異常NameNotFoundException是否被忽視。 |
| ignore-partial-result | false | 指明search時異常PartialResultException是否被忽視。 |
| odm-ref | 使用的ObjectDirectoryMapper的bean id。默認是DefaultObjectDirectoryMapper |
6.4 獲取base LDAP path的值
通常情況下,在contextSource里定義了base LDAP path,然后操作時都是用的相對路徑。但也有某些情況下,需要用到base LDAP path的完整值。比如,操作LDAP groups時,在這里group member的屬性值必須是member的完整DN。
step1:實現接口BaseLdapNameAware
1 package com.example.service; 2 public class PersonService implements PersonService, BaseLdapNameAware { 3 ... 4 private LdapName basePath; 5 6 public void setBaseLdapPath(LdapName basePath) { 7 this.basePath = basePath; 8 } 9 ... 10 private LdapName getFullPersonDn(Person person) { 11 return LdapNameBuilder.newInstance(basePath) 12 .add(person.getDn()) 13 .build(); 14 } 15 ... 16 }
step2:配置BaseLdapPathBeanPostProcessor
1 <beans> 2 ... 3 <ldap:context-source 4 username="cn=Administrator" 5 password="secret" 6 url="ldap://localhost:389" 7 base="dc=261consulting,dc=com" /> 8 ... 9 <bean class="org.springframework.ldap.core.support.BaseLdapPathBeanPostProcessor" /> 10 </beans>
