spring_ldap翻译(一)
作为spring框架的一部分,Spring JDBC提供了十分简单而有效的SQL开发。对Java LDAP,我们需要也需要如此。
第一章 介绍
1.1 概览
Spring-LDAP是一个java简单应用在LDAP开发的一个库,是采取类似Spring JDBC中的JdbcTemplate的原理建立的。它使得我们完全没必要考虑LdapContext的生成和关闭以及NamingEnumeration的循环。在Spring's DataAccessException基础上建立的Spring-LDAP提供一个更加全面且不用检查的异常处理机制。作为补充,Spring-LDAP也有了动态建立LDAP filters和DNs(Distinguished Names)的类。
举个例子来说,如实现一个获取所有人员进入并返回存有他们名字的list的方法。用JDBC,我们得先生成一个connection,用statement执行一个query。然后我们要遍历resultset,找到我们需要的那个column,把它放入到list。类似地,用Java LDAP,我们先生成一个context,用search filter执行一个search。然后循环遍历resulting namingenumeration,找到需要的那个attribute,把它加入到list。
按传统的实现方法,用Java LDAP实现查找人员名称看起来应该是这样的:
?/P>
package com.example.dao;
?/P>
public class TraditionalPersonDaoImpl implements PersonDao {
public List 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”);
?/P>
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException e) {
throw new RuntimeException(e);
}
?/P>
LinkedList list = new LinkedList();
NamingEnumeration results = null;
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
results = ctx.search("", "(objectclass=person)", controls);
?/P>
while (results.hasMore()) {
SearchResult searchResult = (SearchResult) results.next();
Attributes attributes = searchResult.getAttributes();
Attribute attr = attributes.get("cn");
String cn = (String) attr.get();
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 AttributesMapper,我们可以通过下面的代码实现完全一样的功能:
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
public List getAllPersonNames() {
return ldapTemplate.search(
"", "(objectclass=person)",
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
}
}
|
2007-03-21 14:44:18 |
1.2 包
用Spring LDAP最小需要:
- spring-ldap(spring-ldap包)
- spring-core(用于框架内部的丰富的工具类)
- spring-beans(方便操作java beans的接口和类)
- spring-context(增加通过一致API为应用对象获取资源的能力)
- spring-dao(使经常性的错误处理跟使用中的数据访问分开的异常处理机制)
- commons-logging(简单的日志处理,内部使用)
在您的Spring context文件中设置需要的beans,然后把LdapTemplate注入到您的数据访问对象:
<beans>
...
<bean id="contextSource" class="org.springframework.ldap.support.LdapContextSource">
<property name="url" value="ldap://localhost:389" />
<property name="base" value="dc=example,dc=com" />
<property name="userName" value="cn=Manager" />
<property name="password" value="secret" />
</bean>
?/P>
<bean id="ldapTemplate" class="org.springframework.ldap.LdapTemplate">
<constructor-arg ref="contextSource" />
</bean>
...
</beans>
|
|
|
2007-03-21 15:03:15 |
1.3 包架构
这部分包提供了Spring LDAP源代码的逻辑包架构的视图。每个包的依赖性清晰的标注。一个包依赖性是指需要依赖的包来编译这个包,但是运行的时候就不是必须的(依赖您自己要用的这个包)。例如,Spring LDAP 和Acegi Security一起用继承了org.acegisecurity这个包的使用。
1.3.1 org.springframework.ldap
这个ldap包包含了整个库的中心内容。这些内容包括AttributesMapper,ContextSource,和NameClassPairCallbackHandler.这个也包括中心类LdapTemplate.
- 依赖:spring-core,spring-beans,spring-context,spring-dao,commons-logging(TBD).
1.3.2 org.springframework.ldap.support
support包有支持中心接口实现类和DirContextAdapter abstraction。
1.3.3 org.springframework.ldap.support.authentication
support authentication包有用于acegi security的认证资源接口的实现。
- 依赖:ldap,acegi-security(optional)
1.3.4 org.springframework.ldap.support.filter
support filter包有Filter 抽象接口和几个它的实现类。
1.4 支持
Spring LDAP 1.0.3支持Spring 1.2.7以上版本
|
|
|
2007-03-21 15:33:11 |
第二章 基本操作
2.1 使用 AttributesMapper
在下面的例子中我们将用AttributesMapper很容易地得到所有person对象的名字的结果列表。
Example 2.1. AttributesMapper 返回一个简单属性
package com.example.dao;
?/P>
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
?/P>
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
?/P>
public List getAllPersonNames() {
return ldapTemplate.search(
"", "(objectclass=person)",
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
}
}
上面粗题字部分是AttributesMapper的实现,它通过属性名称获取到了需要的属性值,然后返回结果。中心代码是LdapTemplate枚举了所有发现的数据入口,通过调用对每个入口特定的AttributesMapper收集得到结果,然后把结果放入list。list通过search方法返回结果值。
|
|
|
2007-03-21 15:59:37 |
第二章 基本操作
2.1 使用 AttributesMapper
在下面的例子中我们将用AttributesMapper很容易地得到所有person对象的名字的结果列表。
Example 2.1. AttributesMapper 返回一个简单属性
package com.example.dao;
?/P>
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
?/P>
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
?/P>
public List getAllPersonNames() {
return ldapTemplate.search(
"", "(objectclass=person)",
new AttributesMapper() {
public Object mapFromAttributes(Attributes attrs)
throws NamingException {
return attrs.get("cn").get();
}
});
}
}
上面粗题字部分是AttributesMapper的实现,它通过属性名称获取到了需要的属性值,然后返回结果。中心代码是LdapTemplate枚举了所有发现的数据入口,通过调用对每个入口特定的AttributesMapper收集得到结果,然后把结果放入list。list通过search方法返回结果值。
|
|
|
2007-03-21 16:02:21 |
如果你有标志一个入口的distinguished name(dn),你就可以直接获取这个入口,而不用去搜索它。这个在Java LDAP就叫着一个lookup。下面的例子就展示了一个lookup怎样得到person对象的结果集的。
Example 2.3. A lookup resulting in a Person object
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
public Person findPerson(String dn) {
return (Person) ldapTemplate.lookup(dn, new PersonAttributesMapper());
}
}
这里将遍历特别的dn,把发现的属性集发送到已经提供的AttributesMapper,然后得到person对象的结果集。
|
|
|
2007-03-21 16:36:11 |
2.3 建立动态dn
标准的Name interface代表了一个普通的名称,它基本上是一个一定规则的组件序列。在那个序列的Name interface也提供了基本的一些操作,比如添加和删除。LdapTemplate提供了Name interface的实现:DistinguishedName。用这个类将大大的简化了建立distinguished names(dn),特别考虑到有时关于escapings和encodings的复杂规则。下面的例子阐述了DistinguishedName是怎样被用来构造一个dn的。
Example 2.6. Building a distinguished name dynamically
package com.example.dao;
import net.sf.ldaptemplate.support.DistinguishedName;
import javax.naming.Name;
public class PersonDaoImpl implements PersonDao {
public static final String BASE_DN = "dc=example,dc=com";
...
protected Name buildDn(Person p) {
DistinguishedName dn = new DistinguishedName(BASE_DN);
dn.add("c", p.getCountry());
dn.add("ou", p.getCompany());
dn.add("cn", p.getFullname());
return dn;
}
}
假如一个person有以下属性:
country
|
Sweden
|
company
|
Some Company
|
fullname
|
Some Person
|
上面的代码将产生下面dn的结果:
cn=Some Person, ou=Some Company, c=Sweden, dc=example, dc=com
在java5中,有个Name interface的实现:LdapName。
如果你是在用java5,你可能需要用到LdapName。当然,如果你希望用DistinguishedName,那你可以还用DistinguishedName。
|
|
|
2007-03-21 16:56:32 |
2.4 绑定和解绑定
2.4.1 数据绑定
在Java LDAP中插入数据叫做绑定。为了做到绑定,一个唯一标志新entry的dn是必须的。下面的例子展示了数据是如何通过LdapTemplate绑定的:
Example 2.7. Binding data using Attributes
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void create(Person p) {
Name dn = buildDn(p);
ldapTemplate.bind(dn, null, buildAttributes(p));
}
private Attributes buildAttributes(Person p) {
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", "Some Person");
attrs.put("sn", "Person");
return attrs;
}
}
Attributes的建立是在减少和冗长时候起了足够的作用。当然他对进一步的地简化绑定操作提供了可能,这个将在第三章描述。
|
|
|
2007-03-21 17:40:16 |
2.4.2 解绑定数据
在Java LDAP中删除数据就叫着解绑定数据,入口(entry)是需要dn来唯一标志,就像绑定操作一样。下面的例子展示了使用LdapTemplate怎样来解绑定数据:
Example 2.8. Unbinding data
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void delete(Person p) {
Name dn = buildDn(p);
ldapTemplate.unbind(dn);
}
}
|
|
|
2007-03-22 09:16:05 |
2.5 修改
在Java LDAP,数据修改可以有两种方式:使用rebind或者modifyAttributes。
2.5.1 使用rebind修改
使用rebind修改数据是一种比较鲁莽的方式。它基本上就是跟在绑定后面的解绑定。它看起来像这样:
Example 2.9. Modifying using rebind
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void update(Person p) {
Name dn = buildDn(p);
ldapTemplate.rebind(dn, null, buildAttributes(p));
}
}
2.5.2 使用modifyAttributes修改
如果需要修改的属性应该被取代,有一个获取一组修正的方法叫modifyAttributes。
Example 2.10. Modifying using modifyAttributes
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void updateDescription(Person p) {
Name dn = buildDn(p);
Attribute attr = new BasicAttribute("description", p.getDescription())
ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
ldapTemplate.modifyAttributes(dn, new ModificationItem[] {item});
}
}
建立Attributes和ModificationItem 数组是许多工作,但你看到第三章时,修改操作可能变得更简单。
|
|
|
2007-03-22 09:28:30 |
第三章 DirObjectFactory 和 DirContextAdapter
3.1 介绍
有一个鲜为人知的-可能低估的-Java LDAP API的特性,就是能够通过注册一个DirObjectFactory自动从找到的contexts中创建对象。它很少被用到的其中一个理由是因为要使用它你必须要实现实现DirObjectFactory,DirObjectFactory生成实现DirContext的实例。Spring LDAP库提供了缺少的那部分,即实现DirContext的DirContextAdapter和相应实现DirObjectFactory的DefaultDirObjectFactory。DefaultDirObjectFactory和DirContextAdapter一起使用是一个十分强有力的工具。
3.2 使用ContextMapper查询和浏览
DefaultDirObjectFactory是用ContextSource默认生成的,这句话的意思就是无论什么时候在LDAP树上都存在一个context,context的属性和dn将被用来构造一个DirContextAdapter。这样的话,我们就使用ContextMapper而不是AttributesMapper类转换找到的结果值:
Example 3.1. Searching using a ContextMapper
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
...
private static class PersonContextMapper implements ContextMapper {
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter)ctx;
Person p = new Person();
p.setFullName(context.getStringAttribute("cn"));
p.setLastName(context.getStringAttribute("sn"));
p.setDescription(context.getStringAttribute("description"));
return p;
}
}
public Person findByPrimaryKey(
String name, String company, String country) {
Name dn = buildDn(name, company, country);
return ldapTemplate.lookup(dn, new PersonContextMapper());
}
}
上面的代码展示了要获取attributes可以直接通过name,而不用通过Attributes类和BasicAttribute类。
|
|
|
2007-03-22 10:02:54 |
3.3 使用ContextMapper绑定和修改
ContextMapper在绑定和修改数据时也可以用来隐藏Attributes。
3.3.1 绑定
下面是一个优化的实现生成DAO方法的例子。
跟前面讲的的2.4.1实现例子作比较。
Example 3.2. Binding using DirContextAdapter
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
...
public void create(Person p) {
Name dn = buildDn(p);
DirContextAdapter context = new DirContextAdapter(dn);
context.setAttributeValues("objectclass", new String[] {"top", "person"});
context.setAttributeValue("cn", p.getFullname());
context.setAttributeValue("sn", p.getLastname());
context.setAttributeValue("description", p.getDescription());
ldapTemplate.bind(dn, context, null);
}
}
注意我们用获取到的DirContextAdapter作为第二个参数去绑定,本来应该用Context的。第三个参数是null,因为我们没有用到任何的Attributes。
|
|
|
2007-03-22 11:52:17 |
3.3.2 修改
使用跟列子3.2一样的思想,rebind的代码将变得十分优秀,只是调用的方法改成rebind就可以了。这里,让我们来看看如何实现这个问题:如果你不想remove和re-create entry,而只是修改已经改变的属性值。DirContextAdapter是有能力保存修改属性值的路径的。下面的例子充分利用了这个特性:
Example 3.3. Modifying using DirContextAdapter
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
...
public void update(Person p) {
Name dn = buildDn(p);
DirContextAdapter context = (DirContextAdapter)ldapTemplate.lookup(dn);
context.setAttributeValues("objectclass", new String[] {"top", "person"});
context.setAttributeValue("cn", p.getFullname());
context.setAttributeValue("sn", p.getLastname());
context.setAttributeValue("description", p.getDescription());
ldapTemplate.modifyAttributes(dn, context.getModificationItems());
}
}
|
|
|
2007-03-22 11:55:04 |
细心的读者会发现我们已经复用了生成和修改的方法。这个代码把一个domain对象跟一个context匹配。它将是一个特别独立的方法。
Example 3.4. Binding and modifying using DirContextAdapter
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
...
public void create(Person p) {
Name dn = buildDn(p);
DirContextAdapter context = new DirContextAdapter(dn);
mapToContext(p, context);
ldapTemplate.bind(dn, context, null);
}
public void update(Person p) {
Name dn = buildDn(p);
DirContextAdapter context = (DirContextAdapter)ldapTemplate.lookup(dn);
mapToContext(person, context);
ldapTemplate.modifyAttributes(dn, context.getModificationItems());
}
protected void mapToContext (Person p, DirContextAdapter context) {
context.setAttributeValues("objectclass", new String[] {"top", "person"});
context.setAttributeValue("cn", p.getFullName());
context.setAttributeValue("sn", p.getLastName());
context.setAttributeValue("description", p.getDescription());
}
}
|
|
|
2007-03-22 11:56:49 |
3.4 一个完整的PersonDao类
阐述完了spring-LDAP的能力只好,这里也完成了一个完整的用LDAP的PersonDao类的实现,它仅仅只有68行。
Example 3.5. A complete PersonDao class
package com.example.dao;
import java.util.List;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import net.sf.ldaptemplate.AttributesMapper;
import net.sf.ldaptemplate.ContextMapper;
import net.sf.ldaptemplate.LdapTemplate;
import net.sf.ldaptemplate.support.DirContextAdapter;
import net.sf.ldaptemplate.support.DistinguishedName;
import net.sf.ldaptemplate.support.filter.EqualsFilter;
public class PersonDaoImpl implements PersonDao {
private LdapTemplate ldapTemplate;
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
public void create(Person person) {
DirContextAdapter context = new DirContextAdapter();
mapToContext(person, context);
ldapTemplate.bind(buildDn(person), context, null);
}
public void update(Person person) {
Name dn = buildDn(person);
DirContextAdapter context = (DirContextAdapter)ldapTemplate.lookup(dn);
mapToContext(person, context);
ldapTemplate.modifyAttributes(dn, context.getModificationItems());
}
|
|
|
2007-03-22 11:59:52 |
public void delete(Person person) {
ldapTemplate.unbind(buildDn(person));
}
public Person findByPrimaryKey(String name, String company, String country) {
Name dn = buildDn(name, company, country);
return (Person) ldapTemplate.lookup(dn, getContextMapper());
}
public List findAll() {
EqualsFilter filter = new EqualsFilter("objectclass", "person");
return ldapTemplate.search(DistinguishedName.EMPTY_PATH, filter.encode(), getContextMapper());
}
protected ContextMapper getContextMapper() {
return new PersonContextMapper();
}
protected Name buildDn(Person person) {
return buildDn(person.getFullname(), person.getCompany(), person.getCountry());
}
protected Name buildDn(String fullname, String company, String country) {
DistinguishedName dn = new DistinguishedName();
dn.add("c", country);
dn.add("ou", company);
dn.add("cn", fullname);
return dn;
}
|
|
|
2007-03-22 12:01:41 |
protected void mapToContext(Person person, DirContextAdapter context) {
context.setAttributeValues("objectclass", new String[] {"top", "person"});
context.setAttributeValue("cn", person.getFullName());
context.setAttributeValue("sn", person.getLastName());
context.setAttributeValue("description", person.getDescription());
}
private static class PersonContextMapper implements ContextMapper {
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter)ctx;
Person person = new Person();
person.setFullName(context.getStringAttribute("cn"));
person.setLastName(context.getStringAttribute("sn"));
person.setDescription(context.getStringAttribute("description"));
return person;
}
}
}
?/P>
|
注意
|
在一些情况下,一个对象的dn是用对象的属性构造的。例如,在上面的例子,国籍,公司,人的全名都可以被用在dn上,这就意味着修改这些属性的其中任意一个都确实需要在LDAP树上除了要修改Attribute的值还需要使用rename()操作来移动entry。因为这些非常高的实现是需要自己掌握好的一些事情,如果必要的话,也是不允许用户改变这些属性或者在update()方法里使用rename()操作的
|
|
|
|
2007-03-22 15:46:33 |
第四章补充缺省的负载API方法
4.1 实现普通的搜索方法
因为LdapTemplate含有几个负载版本,这几个版本是关于用DirContext的最普通操作的,所以我们不得不为每一个方法提供一个可选的标签,主要是因为他们太多了。
因此,我们必须提供一种方法去调用你需要的负载方法。例如,让我们看一下你需要用下面的方法:
NamingEnumeration search(Name name, String filterExpr, Object[] filterArgs, SearchControls ctls)
这个方法是使用一个普通的SearchExecutor实现:
public interface SearchExecutor {
public NamingEnumeration executeSearch(DirContext ctx) throws NamingException;
}
Example 4.1. A custom search method using SearchExecutor and AttributesMapper
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
...
public List search(final Name base, final String filter, final String[] params,
final SearchControls ctls) {
SearchExecutor executor = new SearchExecutor() {
public NamingEnumeration executeSearch(DirContext ctx) {
return ctx.search(base, filter, params, ctls);
}
};
NameClassPairCallbackHandler handler =
ldapTemplate.new AttributesMapperCallbackHandler(new PersonAttributesMapper());
return ldapTemplate.search(executor, handler);
}
}
|
|
|
2007-03-22 16:44:25 |
如果你更喜欢用ContextMapper而不是AttributesMapper,那就应该是这样:
Example 4.2. A custom search method using SearchExecutor and ContextMapper
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
...
public List search(final Name base, final String filter, final String[] params,
final SearchControls ctls) {
SearchExecutor executor = new SearchExecutor() {
public NamingEnumeration executeSearch(DirContext ctx) {
return ctx.search(base, filter, params, ctls);
}
};
NameClassPairCallbackHandler handler =
ldapTemplate.new ContextMapperCallbackHandler(new PersonContextMapper());
return ldapTemplate.search(executor, handler);
}
}
注意:
当我们使用LdapTemplate.ContextMapperCallbackhandler的时候,你必须确保你已经在SearchControls里面调用了setReturningObjFlag(true)
|
|
|
2007-03-22 16:47:20 |
4.2 实现其他普通的Context方法
采取实现custom search方法一样的方式,你的确可以在ContextExecutor调用DirContext执行任何方法。
public interface ContextExecutor {
public Object executeWithContext(DirContext ctx) throws NamingException;
}
实现ContextExecutor 时,你可以选择使用executeReadOnly()或者使用executeReadWrite方法。我们需要调用这个方法:
Object lookupLink(Name name)
它对DirContext是十分有用的,但是在LdapTemplate没有对应的方法。它是一个lookup方法,因此它只能是read-only。我们可以像这样实现它:
Example 4.3. A custom DirContext method using ContextExecutor
package com.example.dao;
public class PersonDaoImpl implements PersonDao {
...
public Object lookupLink(final Name name) {
ContextExecutor executor = new ContextExecutor() {
public Object executeWithContext(DirContext ctx) {
return ctx.lookupLink(name);
}
};
return ldapTemplate.executeReadOnly(executor);
}
}
同样地,你也可以使用executeReadWrite方法执行一个read-write操作。
|
|
|
2007-03-22 17:14:05 |
第五章 配置
5.1 ContextSource 配置
在AbstractContextSource (DirContextSource和LdapContextSource的父类)有几个属性可以用来修改它自己的动作。
5.1.1 LDAP服务器URLS
有时可能需要使用urls属性配置多个可选的LDAP服务器,这种情况需要使用一个string 数组把提供的服务器urls保存到urls属性里。
5.1.2 权限
权限的contexts是有默认的read-only和read-write操作生成的。你可以通过使用ContextSource的认证指定LDAP用户的用户名和密码。
注意:
用户名必须和用户的dn完全匹配。
一些LDAP服务器设置用于匿名只读访问。如果你想使用匿名的Contexts做只读操作,那把属性anonymousReadOnly 设置为true。
|
|
|
2007-03-22 17:35:54 |
5.1.2.1 使用Acegi做custom 认证
使用用户名和密码产生的一个权限上下文默认是静态的-在启动的ContextSource上的这些设置将贯穿整个ContextSource的生命周期-然而有些情况是不想碰到的。 当为那些用户执行LDAP操作时,一个为当前用户设定信任认证的场景就要被用到。这种场景可以通过提供一个AuthenticationSource的实现到启动时的ContextSource方式实现,而不是明确地指定用户名和密码。AuthenticationSource 每次将查询ContextSource的信任认证,一个受信任的Context将会产生。
Example 5.1. The Spring bean definition for an AcegiAuthenticationSource
<beans>
...
<bean id="contextSource" class="org.springframework.ldap.support.LdapContextSource">
<property name="url" value="ldap://localhost:389" />
<property name="base" value="dc=example,dc=com" />
<property name="acegiAuthenticationSource" ref="authenticationSource" />
</bean>
<bean id="acegiAuthenticationSource"
class="org.springframework.ldap.support.authentication.AcegiAuthenticationSource" />
...
</beans>
注:
在使用AuthenticationSource时候,我们不能指定一个用户名和密码到我们的ContextSource 。这些属性只是在默认的behaviour被用到的时候需要。
当用AcegiAuthenticationSource你需要用到Acegi's LdapAuthenticationProvider做认证的时候,用户是跟LDAP相反的。
|
|
|
2007-03-22 17:51:12 |
5.1.2.2 默认的认证
用AcegiAuthenticationSource的时候,认证的上下文将可能在用户使用acegi刚刚登陆的时候就产生了。当用户没有登陆的时候将使用默认的上下文,即使用DefaultValuesAuthenticationSourceDecorator:
Example 5.2. Configuring a DefaultValuesAuthenticationSourceDecorator
<beans>
...
<bean id="contextSource" class="org.springframework.ldap.support.LdapContextSource">
<property name="url" value="ldap://localhost:389" />
<property name="base" value="dc=example,dc=com" />
<property name="authenticationSource" ref="authenticationSource" />
</bean>
<bean id="authenticationSource"
class="org.springframework.ldap.support.DefaultValuesAuthenticationSourceDecorator">
<property name="target" ref="acegiAuthenticationSource" />
<property name="defaultUser" value="cn=myDefaultUser" />
<property name="defaultPassword" value="pass" />
</bean>
<bean id="acegiAuthenticationSource"
class="org.springframework.ldap.support.authentication.AcegiAuthenticationSource" />
...
</beans>
|
|
|
2007-03-22 18:02:45 |
5.1.3 池
LDAP连接池可以通过使用连接标志进行打开和关闭,默认是true。LDAP连接池的配置是通过使用系统的属性来管理的,因此这需要手工处理。连接池的配置可以在这里找到。
5.1.4 ContextSource 高级配置
5.1.4.1 改变ContextFactory
当使用contextFactory 属性生成Contexts的时候, 配置ContextFactory可能要用到ContextSource。它的默认值是com.sun.jndi.ldap.LdapCtxFactory。
5.1.4.2 一般的DirContext环境属性
有些情况下用户除了要根据AbstractContextSource直接配置环境,还需要指定附加的环境设置属性。一些属性应该设置在一个map中,用来设置baseEnvironmentProperties 属性。
|
|
|
2007-03-22 18:18:44 |
5.2 LdapTemplate 配置
5.2.1 忽略的PartialResultExceptions
一些AD服务器是不能自动往下继承的,这样通常导致在查找过程中抛出PartialResultExceptions异常。你可以指定通过把ignorePartialResultException 的属性置为true来忽略PartialResultExceptions异常。
注:
这会引起所有的referals被忽略,而且PartialResultExceptions已经发生了也不会有通知报出。现在没有什么方法可以使用LdapTemplate来对following referrals进行操作。
|
|