空间站

北极心空

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks


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();

            }

         });

   }

}

spring_ldap翻译(二)
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>

 


 

spring_ldap翻译(三)
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。

  •    依赖:ldap

   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 抽象接口和几个它的实现类。

  •    依赖:commons-lang

 

1.4 支持

  Spring LDAP 1.0.3支持Spring 1.2.7以上版本


spring_ldap翻译(四)
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方法返回结果值。

 


spring_ldap翻译(五)
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方法返回结果值。


spring_ldap翻译(六)
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对象的结果集。

spring_ldap翻译(八)
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。

spring_ldap翻译(九)
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的建立是在减少和冗长时候起了足够的作用。当然他对进一步的地简化绑定操作提供了可能,这个将在第三章描述。

spring_ldap翻译(十)
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);

   }

}

spring_ldap翻译(十一)
2007-03-22 09:16:05

 

25 修改

 

       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});

   }

}

 

建立AttributesModificationItem 数组是许多工作,但你看到第三章时,修改操作可能变得更简单。

spring_ldap翻译(十二)
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类。

spring_ldap翻译(十三)
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。

spring_ldap翻译(十四)
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());

   }

}

spring_ldap翻译(十五)
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());

   }

}

spring_ldap翻译(十六)
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());

   }

 

spring_ldap翻译(十七)
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;

   }

 

 

spring_ldap翻译(十八)
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()操作的

 

spring_ldap翻译(十九)
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);

   }

}

spring_ldap翻译(二十)
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)

spring_ldap翻译(二十一)
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操作。

spring_ldap翻译(二十二)
2007-03-22 17:14:05
第五章 配置
5.1 ContextSource 配置
  在AbstractContextSource (DirContextSource和LdapContextSource的父类)有几个属性可以用来修改它自己的动作。
  5.1.1 LDAP服务器URLS
  LDAP服务器URLs是用url属性指定的。URL应该是这种格式的:ldap://myserver.example.com:389。对于SSL访问,用ldaps protocol和对应的端口,如:ldaps://myserver.example.com:636
 
   有时可能需要使用urls属性配置多个可选的LDAP服务器,这种情况需要使用一个string 数组把提供的服务器urls保存到urls属性里。
 
  5.1.2 权限
 
  权限的contexts是有默认的read-only和read-write操作生成的。你可以通过使用ContextSource的认证指定LDAP用户的用户名和密码。
  注意:
  用户名必须和用户的dn完全匹配。
 
 一些LDAP服务器设置用于匿名只读访问。如果你想使用匿名的Contexts做只读操作,那把属性anonymousReadOnly 设置为true。
 
spring_ldap翻译(二十三)
2007-03-22 17:35:54
5.1.2.1 使用Acegi做custom 认证
 
  使用用户名和密码产生的一个权限上下文默认是静态的-在启动的ContextSource上的这些设置将贯穿整个ContextSource的生命周期-然而有些情况是不想碰到的。 当为那些用户执行LDAP操作时,一个为当前用户设定信任认证的场景就要被用到。这种场景可以通过提供一个AuthenticationSource的实现到启动时的ContextSource方式实现,而不是明确地指定用户名和密码。AuthenticationSource 每次将查询ContextSource的信任认证,一个受信任的Context将会产生。
 
  用户使用当前登陆获得的权限认证信息,通过Acegi Security调用AcegiAuthenticationSource:

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相反的。

spring_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>

spring_ldap翻译(二十五)
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 属性。
 
spring_ldap翻译(二十六)
2007-03-22 18:18:44
 5.2 LdapTemplate 配置
  5.2.1 忽略的PartialResultExceptions
  一些AD服务器是不能自动往下继承的,这样通常导致在查找过程中抛出PartialResultExceptions异常。你可以指定通过把ignorePartialResultException 的属性置为true来忽略PartialResultExceptions异常。
 
 注:
 这会引起所有的referals被忽略,而且PartialResultExceptions已经发生了也不会有通知报出。现在没有什么方法可以使用LdapTemplate来对following referrals进行操作。

 
posted on 2007-07-13 11:28 芦苇 阅读(2310) 评论(0)  编辑  收藏 所属分类: JAVA其他

只有注册用户登录后才能发表评论。


网站导航: