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 LdapNameBuilder
import 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 中提取值
LdapUtils
import 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 提供更多帮助以简化这些操作。