Basic Usage
本部分介绍了使用 Spring LDAP 的基础知识。其中包含以下内容:
Search and Lookup Using AttributesMapper
以下示例使用 AttributesMapper 来构建所有用户对象的通用名称列表。
AttributesMapper that returns a single attributeimport 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"))
.toList(*(Attributes attrs) -> (String) attrs.get("cn").get()*);
}
}
AttributesMapper 的内联实现从 Attributes 对象获取期望的属性值并将其返回。在内部,LdapClient 迭代遍历找到的所有条目,为每个条目调用给定的 AttributesMapper,并将结果收集到一个列表中。然后,search 方法返回该列表。
请注意,AttributesMapper 实现可以很容易地修改为返回完整的 Person 对象,如下所示:
import static org.springframework.ldap.query.LdapQueryBuilder.query;
public class PersonRepoImpl implements PersonRepo {
private LdapClient ldapClient;
...
*private class PersonAttributesMapper implements AttributesMapper<Person> {
public Person mapFromAttributes(Attributes attrs) throws NamingException {
Person person = new Person();
person.setFullName((String)attrs.get("cn").get());
person.setLastName((String)attrs.get("sn").get());
person.setDescription((String)attrs.get("description").get());
return person;
}
}*
public List<Person> getAllPersons() {
return ldapClient.search()
.query(query().where("objectclass").is("person"))
.toList(new PersonAttributesMapper());
}
}
LDAP 中的条目通过它们的 distinguished name (DN) 来唯一标识。如果您有条目的 DN,则可以直接检索该条目,而不必查询它。在 Java LDAP 中这称为“lookup”。以下示例展示如何查找 Person 对象:
public class PersonRepoImpl implements PersonRepo {
private LdapClient ldapClient;
...
public Person findPerson(String dn) {
return ldapClient.search().name(dn).toObject(new PersonAttributesMapper());
}
}
前面的示例查找指定的 DN,并将找到的属性传递给提供的 AttributesMapper,在这种情况下,将生成一个 Person 对象。
Building LDAP Queries
LDAP 搜索涉及一些参数,包括以下内容:
-
基础 LDAP 路径:搜索应在 LDAP 树中的哪个位置开始。
-
搜索范围:搜索应在 LDAP 树中深入到哪个级别。
-
Attributes to return.
-
搜索过滤器:在选择范围内的元素时要使用的条件。
Spring LDAP 提供一个带有用于构建 LDAP 查询的流畅 API 的 LdapQueryBuilder。
假设你要执行从基本 DN dc=261consulting,dc=com 开始的搜索,将返回的属性限制为 cn 和 sn,过滤器为 (&(objectclass=person)(sn=?)),其中我们要将 ? 替换为 lastName 参数。以下示例演示了如何使用 LdapQueryBuilder 进行此操作:
*import static org.springframework.ldap.query.LdapQueryBuilder.query;*
public class PersonRepoImpl implements PersonRepo {
private LdapClient ldapClient;
...
public List<String> getPersonNamesByLastName(String lastName) {
*LdapQuery query = query()
.base("dc=261consulting,dc=com")
.attributes("cn", "sn")
.where("objectclass").is("person")
.and("sn").is(lastName);*
return ldapClient.search().query(*query*)
.toObject((Attributes attrs) -> (String) attrs.get("cn").get());
}
}
|
除了简化构建复杂搜索参数外, |
|
|
|
|
有关 LdapQueryBuilder 的更多信息,请参见 Advanced LDAP Queries。
Dynamically Building Distinguished Names
在解析识别名时,识别名的标准 Java 实现 ( LdapName) 运行良好。然而,在实际使用中,此实现有一些缺点:
-
`LdapName`实现是可变的,这并不适合表示标识的对象。
-
尽管具有可变性,但使用 `LdapName`动态构建还是修改专有名称的 API 非常繁琐。提取索引值或(尤其)的命名组件值也有些麻烦。
-
`LdapName`中的许多操作都会抛出已检查异常,在错误通常是致命的并且无法以有意义的方式修复时,需要 `try-catch`语句。
为了简化识别名的使用,Spring LDAP 提供 LdapNameBuilder,以及 LdapUtils 中的一些实用方法,这些方法在处理 LdapName 时有所帮助。
Examples
本节提供几个在前面各节中涵盖的主题的示例。第一个示例使用 LdapNameBuilder 动态构建 LdapName:
LdapName by using LdapNameBuilderimport org.springframework.ldap.support.LdapNameBuilder;
import javax.naming.Name;
public class PersonRepoImpl implements PersonRepo {
public static final String BASE_DN = "dc=example,dc=com";
protected Name buildDn(Person p) {
*return LdapNameBuilder.newInstance(BASE_DN)
.add("c", p.getCountry())
.add("ou", p.getCompany())
.add("cn", p.getFullname())
.build();*
}
...
}
假设 Person 具有以下属性:
| Attribute Name | Attribute Value |
|---|---|
|
Sweden |
|
Some Company |
|
Some Person |
然后前述代码将生成以下 distinguished name:
cn=Some Person, ou=Some Company, c=Sweden, dc=example, dc=com
以下示例使用 LdapUtils 从 distinguished name 中提取值
LdapUtilsimport org.springframework.ldap.support.LdapNameBuilder;
import javax.naming.Name;
public class PersonRepoImpl implements PersonRepo {
...
protected Person buildPerson(Name dn, Attributes attrs) {
Person person = new Person();
person.setCountry(*LdapUtils.getStringValue(dn, "c")*);
person.setCompany(*LdapUtils.getStringValue(dn, "ou")*);
person.setFullname(*LdapUtils.getStringValue(dn, "cn")*);
// Populate rest of person object using attributes.
return person;
}
}
由于 1.4 及更早版本的 Java 根本不提供任何公共 Distinguished Name 实现,Spring LDAP 1.x 因此提供了自己的实现 DistinguishedName。该实现自有几个缺陷,并且已在 2.0 版中弃用。您现在应使用 LdapName 以及前面描述的实用程序。
Binding and Unbinding
本部分介绍如何增添和删除数据。更新的内容涵盖在 next section 中。
Adding Data
在 Java LDAP 中插入数据称为绑定。这有些令人困惑,因为在 LDAP 术语中,“bind”表示完全不同的内容。JNDI 绑定执行 LDAP Add 操作,将具有指定 distinguished name 的新条目与一组属性相关联。以下示例使用 LdapClient 添加数据:
public class PersonRepoImpl implements PersonRepo {
private LdapClient ldapClient;
...
public void create(Person p) {
Name dn = buildDn(p);
*ldapClient.bind(dn).attributes(buildAttributes(p)).execute();*
}
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;
}
}
手动构建属性虽然单调且冗长,但足以满足很多目的。然而,你可以进一步简化绑定操作,如 Simplifying Attribute Access and Manipulation with DirContextAdapter 所述。
Removing Data
在 Java LDAP 中删除数据称为解除绑定。JNDI 解除绑定执行 LDAP Delete 操作,从 LDAP 树中删除与指定 distinguished name 相关联的条目。以下示例使用 LdapClient 删除数据:
public class PersonRepoImpl implements PersonRepo {
private LdapClient ldapClient;
...
public void delete(Person p) {
Name dn = buildDn(p);
*ldapClient.unbind(dn).execute();*
}
}
Updating
在 Java LDAP 中,可以通过两种方式修改数据:使用 rebind,或者使用 modifyAttributes。
Updating by Using Rebind
rebind 是一种原始的数据修改方式。它实质上是一个 unbind,后跟一个 bind。以下示例调用 LDAP 的 rebind:
public class PersonRepoImpl implements PersonRepo {
private LdapClient ldapClient;
...
public void update(Person p) {
Name dn = buildDn(p);
*ldapTemplate.bind(dn).attributes(buildAttributes(p)).replaceExisting(true).execute();*
}
}
Updating by Using modifyAttributes
一种更复杂的数据修改方式是使用 modifyAttributes。此操作采用一个显式属性修改数组,并将其应用于一个特定的条目,如下图所示:
public class PersonRepoImpl implements PersonRepo {
private LdapClient ldapClient;
...
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.modify().name(dn).attributes(item).execute();*
}
}
构建 Attributes 和 ModificationItem 数组需要很多工作。但是,正如我们在 Simplifying Attribute Access and Manipulation with DirContextAdapter 中所述,Spring LDAP 提供更多帮助以简化这些操作。