基本用法

搜索和查找方式AttributesMapper

下面的示例使用 AttributesMapper 构建一个 List 所有 person 对象的所有通用名称。spring-doc.cn

示例 1. 返回单个属性AttributesMapper
import 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());
   }
}

的内联实现从对象中获取所需的属性值并返回它。在内部,迭代找到的所有条目,为每个条目调用 given,并将结果收集到一个列表中。然后,该方法返回该列表。AttributesMapperAttributesLdapClientAttributesMappersearchspring-doc.cn

请注意,可以很容易地修改实现以返回完整的对象,如下所示:AttributesMapperPersonspring-doc.cn

示例 2.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 中的条目由其专有名称 (DN) 唯一标识。 如果您有条目的 DN,则可以直接检索该条目,而无需查询它。 这在 Java LDAP 中称为 “查找”。以下示例显示了对象的查找:Personspring-doc.cn

例 3.生成 Person 对象的查找
public class PersonRepoImpl implements PersonRepo {
   private LdapClient ldapClient;
   ...
   public Person findPerson(String dn) {
      return ldapClient.search().name(dn).toObject(new PersonAttributesMapper());
   }
}

前面的示例查找指定的 DN 并将找到的属性传递给提供的属性 — 在本例中,生成一个对象。AttributesMapperPersonspring-doc.cn

构建 LDAP 查询

LDAP 搜索涉及许多参数,包括:spring-doc.cn

  • Base LDAP path(基本 LDAP 路径):搜索在 LDAP 树中的开始位置。spring-doc.cn

  • 搜索范围:搜索应在 LDAP 树中的深度。spring-doc.cn

  • 要返回的属性。spring-doc.cn

  • 搜索过滤器:选择范围内的元素时使用的条件。spring-doc.cn

Spring LDAP 为LdapQueryBuilder提供了用于构建 LDAP 查询的 Fluent API。spring-doc.cn

假设您要从基本 DN 开始执行搜索 , 将返回的属性限制为 和 ,并使用过滤器 ,我们希望将 替换为参数的值。 以下示例演示如何使用 :dc=261consulting,dc=comcnsn(&(objectclass=person)(sn=?))?lastNameLdapQueryBuilderspring-doc.cn

示例 4.动态构建搜索过滤器
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());
   }
}
除了简化复杂搜索参数的构建之外,the 及其关联的类还提供了对搜索过滤器中任何不安全字符的正确转义。这可以防止“LDAP 注入”,即用户可能会使用此类字符将不需要的操作注入到 LDAP 操作中。LdapQueryBuilder
LdapClient包括许多用于执行 LDAP 搜索的重载方法。这是为了适应尽可能多的不同用例和编程风格偏好。对于绝大多数使用案例,建议使用将 作为输入的方法。LdapQuery
这是您在处理搜索和查找数据时可以使用的唯一可用回调接口之一。有关替代方案,请参见使用 DirContextAdapter 简化属性访问和操作AttributesMapper

有关 的更多信息,请参阅高级 LDAP 查询LdapQueryBuilderspring-doc.cn

动态构建可分辨名称

专有名称 (LdapName) 的标准 Java 实现 在解析 Distinguished Names 时表现良好。但是,在实际使用中,此实现存在许多缺点:spring-doc.cn

  • 该实现是可变的,这非常适合于表示身份的对象。LdapNamespring-doc.cn

  • 尽管具有可变性,但用于动态构建或修改可分辨名称的 API 非常繁琐。 提取索引或(特别是)命名组件的值也有点尴尬。LdapNamespring-doc.cn

  • 对 throw checked 异常的许多操作都需要 statement,用于错误通常是致命的并且无法以有意义的方式修复的情况。LdapNametry-catchspring-doc.cn

为了简化使用专有名称, Spring LDAP 提供了一个LdapNameBuilder, 以及 LdapUtils 中的许多实用程序方法,这些方法在使用 .LdapNamespring-doc.cn

例子

本节提供了前面几节中涵盖的主题的几个示例。 第一个示例使用 :LdapNameLdapNameBuilderspring-doc.cn

例 5.使用LdapNameLdapNameBuilder
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();
  }
  ...
}

假设 a 具有以下属性:Personspring-doc.cn

属性名称 属性值

countryspring-doc.cn

瑞典spring-doc.cn

companyspring-doc.cn

某公司spring-doc.cn

fullnamespring-doc.cn

某人spring-doc.cn

然后,前面的代码将产生以下可分辨名称:spring-doc.cn

cn=Some Person, ou=Some Company, c=Sweden, dc=example, dc=com

以下示例使用LdapUtilsspring-doc.cn

例 6.使用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 之前(包括 1.4)的 Java 版本根本没有提供任何公共的专有名称实现,因此 Spring LDAP 1.x 提供了自己的实现。 此实现存在一些缺点,并且在 2.0 版中已被弃用。现在,您应该与前面描述的实用程序一起使用。DistinguishedNameLdapNamespring-doc.cn

绑定和解绑

本节介绍如何添加和删除数据。更新 将在下一节中介绍。spring-doc.cn

添加数据

在 Java LDAP 中插入数据称为绑定。这有点令人困惑,因为在 LDAP 术语中,“bind” 的含义完全不同。 JNDI 绑定执行 LDAP Add 操作,将具有指定可分辨名称的新条目与一组属性相关联。 以下示例使用 添加数据 :LdapClientspring-doc.cn

例 7.使用 Attributes 添加数据
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;
   }
}

手动属性构建虽然枯燥乏味,但足以满足多种用途。但是,你可以进一步简化绑定操作,如使用DirContextAdapter简化属性访问和操作中所述。spring-doc.cn

删除数据

删除 Java LDAP 中的数据称为取消绑定。 JNDI 取消绑定执行 LDAP 删除操作,从 LDAP 树中删除与指定的专有名称关联的条目。 以下示例使用 删除数据 :LdapClientspring-doc.cn

例 8.删除数据
public class PersonRepoImpl implements PersonRepo {
   private LdapClient ldapClient;
   ...
   public void delete(Person p) {
      Name dn = buildDn(p);
      ldapClient.unbind(dn).execute();
   }
}

更新

在 Java LDAP 中,可以通过两种方式修改数据:使用 或 使用 。rebindmodifyAttributesspring-doc.cn

使用 Rebind 进行更新

A 是修改数据的粗略方法。它基本上是一个后跟一个 . 以下示例调用 LDAP 的 :rebindunbindbindrebindspring-doc.cn

例 9.使用 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();
   }
}

使用 更新modifyAttributes

修改数据的更复杂的方法是使用 .此操作采用一组显式属性修改 并对特定条目执行它们,如下所示:modifyAttributesspring-doc.cn

例 10.使用 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();
   }
}

构建和数组是一项繁重的工作。但是,正如我们在使用 DirContextAdapter 简化属性访问和操作中所描述的那样, Spring LDAP 为简化这些操作提供了更多帮助。AttributesModificationItemspring-doc.cn