Basic Usage
本部分介绍了使用 Spring LDAP 的基础知识。其中包含以下内容:
This section describes the basics of using Spring LDAP. It contains the following content:
Search and Lookup Using AttributesMapper
以下示例使用 AttributesMapper
来构建所有用户对象的通用名称列表。
The following example uses an AttributesMapper
to build a List of all the common names of all the person objects.
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
方法返回该列表。
The inline implementation of AttributesMapper
gets the desired attribute value from the Attributes
object and returns it. Internally, LdapClient
iterates over all entries found, calls the given AttributesMapper
for each entry, and collects the results in a list. The list is then returned by the search
method.
请注意,AttributesMapper
实现可以很容易地修改为返回完整的 Person
对象,如下所示:
Note that the AttributesMapper
implementation could easily be modified to return a full Person
object, as follows:
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
对象:
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 querying for it.
This is called a “lookup” in Java LDAP. The following example shows a lookup for a Person
object:
public class PersonRepoImpl implements PersonRepo {
private LdapClient ldapClient;
...
public Person findPerson(String dn) {
return ldapClient.search().name(dn).toObject(new PersonAttributesMapper());
}
}
前面的示例查找指定的 DN,并将找到的属性传递给提供的 AttributesMapper
,在这种情况下,将生成一个 Person
对象。
The preceding example looks up the specified DN and passes the found attributes to the supplied AttributesMapper
— in this case, resulting in a Person
object.
Building LDAP Queries
LDAP 搜索涉及一些参数,包括以下内容:
LDAP searches involve a number of parameters, including the following:
-
Base LDAP path: Where in the LDAP tree should the search start.
-
Search scope: How deep in the LDAP tree should the search go.
-
Attributes to return.
-
Search filter: The criteria to use when selecting elements within scope.
Spring LDAP 提供一个带有用于构建 LDAP 查询的流畅 API 的 LdapQueryBuilder
。
Spring LDAP provides an LdapQueryBuilder
with a fluent API for building LDAP Queries.
假设你要执行从基本 DN dc=261consulting,dc=com
开始的搜索,将返回的属性限制为 cn
和 sn
,过滤器为 (&(objectclass=person)(sn=?))
,其中我们要将 ?
替换为 lastName
参数。以下示例演示了如何使用 LdapQueryBuilder
进行此操作:
Suppose you want to perform a search starting at the base DN dc=261consulting,dc=com
,
limiting the returned attributes to cn
and sn
, with a filter of (&(objectclass=person)(sn=?))
, where we want the ?
to be replaced with the value of the lastName
parameter.
The following example shows how to do it by using the 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());
}
}
除了简化构建复杂搜索参数外, |
In addition to simplifying building of complex search parameters, the |
|
|
|
The |
有关 LdapQueryBuilder
的更多信息,请参见 Advanced LDAP Queries。
For more information on the LdapQueryBuilder
, see Advanced LDAP Queries.
Dynamically Building Distinguished Names
在解析识别名时,识别名的标准 Java 实现 ( LdapName
) 运行良好。然而,在实际使用中,此实现有一些缺点:
The standard Java implementation of Distinguished Name (LdapName
)
performs well when it comes to parsing Distinguished Names. However, in practical use, this implementation has a number of shortcomings:
-
The
LdapName
implementation is mutable, which is badly suited for an object that represents identity. -
Despite its mutable nature, the API for dynamically building or modifying Distinguished Names by using
LdapName
is cumbersome. Extracting values of indexed or (particularly) named components is also a little bit awkward. -
Many of the operations on
LdapName
throw checked exceptions, requiringtry-catch
statements for situations where the error is typically fatal and cannot be repaired in a meaningful manner.
为了简化识别名的使用,Spring LDAP 提供 LdapNameBuilder
,以及 LdapUtils
中的一些实用方法,这些方法在处理 LdapName
时有所帮助。
To simplify working with Distinguished Names, Spring LDAP provides an LdapNameBuilder
,
as well as a number of utility methods in LdapUtils
that help when working with LdapName
.
Examples
本节提供几个在前面各节中涵盖的主题的示例。第一个示例使用 LdapNameBuilder
动态构建 LdapName
:
This section presents a few examples of the subjects covered in the preceding sections.
The first example dynamically builds an LdapName
by using LdapNameBuilder
:
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
具有以下属性:
Assume that a Person
has the following attributes:
Attribute Name | Attribute Value |
---|---|
|
Sweden |
|
Some Company |
|
Some Person |
然后前述代码将生成以下 distinguished name:
The preceding code would then result in the following distinguished name:
cn=Some Person, ou=Some Company, c=Sweden, dc=example, dc=com
以下示例使用 LdapUtils
从 distinguished name 中提取值
The following example extracts values from a distinguished name by using LdapUtils
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
以及前面描述的实用程序。
Since Java versions prior to and including 1.4 did not provide any public Distinguished Name implementation at all, Spring LDAP 1.x provided its own implementation, DistinguishedName
.
This implementation suffered from a couple of shortcomings of its own and has been deprecated in version 2.0. You should now use LdapName
along with the utilities described earlier.
Binding and Unbinding
本部分介绍如何增添和删除数据。更新的内容涵盖在 next section 中。
This section describes how to add and remove data. Updating is covered in the next section.
Adding Data
在 Java LDAP 中插入数据称为绑定。这有些令人困惑,因为在 LDAP 术语中,“bind
”表示完全不同的内容。JNDI 绑定执行 LDAP Add 操作,将具有指定 distinguished name 的新条目与一组属性相关联。以下示例使用 LdapClient
添加数据:
Inserting data in Java LDAP is called binding. This is somewhat confusing, because in LDAP terminology, “bind” means something completely different.
A JNDI bind performs an LDAP Add operation, associating a new entry that has a specified distinguished name with a set of attributes.
The following example adds data by using 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
所述。
Manual attributes building is — while dull and verbose — sufficient for many purposes. You can, however, simplify the binding operation further, as described in Simplifying Attribute Access and Manipulation with DirContextAdapter
.
Removing Data
在 Java LDAP 中删除数据称为解除绑定。JNDI 解除绑定执行 LDAP Delete 操作,从 LDAP 树中删除与指定 distinguished name 相关联的条目。以下示例使用 LdapClient
删除数据:
Removing data in Java LDAP is called unbinding.
A JNDI unbind performs an LDAP Delete operation, removing the entry associated with the specified distinguished name from the LDAP tree.
The following example removes data by using 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
。
In Java LDAP, data can be modified in two ways: either by using rebind
or by using modifyAttributes
.
Updating by Using Rebind
rebind
是一种原始的数据修改方式。它实质上是一个 unbind
,后跟一个 bind
。以下示例调用 LDAP 的 rebind
:
A rebind
is a crude way to modify data. It is basically an unbind
followed by a bind
.
The following example invokes LDAP’s 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
。此操作采用一个显式属性修改数组,并将其应用于一个特定的条目,如下图所示:
A more sophisticated way of modifying data is to use modifyAttributes
. This operation takes an array of explicit attribute modifications
and performs them on a specific entry, as follows:
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 提供更多帮助以简化这些操作。
Building Attributes
and ModificationItem
arrays is a lot of work. However, as we describe in Simplifying Attribute Access and Manipulation with DirContextAdapter
,
Spring LDAP provides more help for simplifying these operations.