基本用法

使用AttributesMapper進行搜尋和查詢

以下示例使用AttributesMapper來構建所有人員物件的通用名稱列表。

示例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());
   }
}

AttributesMapper的內聯實現從Attributes物件獲取所需的屬性值並返回它。在內部,LdapClient遍歷所有找到的條目,為每個條目呼叫給定的AttributesMapper,並將結果收集到一個列表中。然後,該列表由search方法返回。

請注意,AttributesMapper實現可以很容易地修改為返回一個完整的Person物件,如下所示

示例2. 返回一個Person物件的AttributesMapper
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中稱為“查詢”。以下示例顯示了Person物件的查詢

示例3. 查詢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物件。

構建LDAP查詢

LDAP搜尋涉及許多引數,包括以下內容

  • 基本LDAP路徑:搜尋應從LDAP樹中的何處開始。

  • 搜尋範圍:搜尋應在LDAP樹中深入到何處。

  • 要返回的屬性。

  • 搜尋過濾器:在選擇範圍內的元素時要使用的標準。

Spring LDAP提供了一個LdapQueryBuilder,它具有用於構建LDAP查詢的流式API。

假設您要執行從基本DN dc=261consulting,dc=com開始的搜尋,將返回的屬性限制為cnsn,過濾器為(&(objectclass=person)(sn=?)),其中我們希望將?替換為lastName引數的值。以下示例顯示瞭如何使用LdapQueryBuilder來完成此操作

示例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());
   }
}
除了簡化複雜搜尋引數的構建之外,LdapQueryBuilder及其相關類還提供了對搜尋過濾器中任何不安全字元的正確轉義。這可以防止“LDAP注入”,即使用者可能會使用此類字元將不需要的操作注入到您的LDAP操作中。
LdapClient包含許多過載方法用於執行LDAP搜尋。這是為了適應儘可能多的不同用例和程式設計風格偏好。對於絕大多數用例,建議使用接受LdapQuery作為輸入的方法。
AttributesMapper只是在處理搜尋和查詢資料時可以使用的回撥介面之一。有關替代方案,請參閱使用DirContextAdapter簡化屬性訪問和操作

有關LdapQueryBuilder的更多資訊,請參閱高階LDAP查詢

動態構建判別名

判別名(LdapName)的標準Java實現,在解析判別名方面表現良好。然而,在實際使用中,此實現存在一些缺點

  • LdapName實現是可變的,這對於表示身份的物件來說非常不合適。

  • 儘管其可變性,但使用LdapName動態構建或修改判別名的API很笨拙。提取索引或(特別是)命名元件的值也有些尷尬。

  • LdapName上的許多操作都會丟擲檢查異常,這需要try-catch語句來處理錯誤通常是致命的且無法以有意義的方式修復的情況。

為了簡化判別名的處理,Spring LDAP提供了LdapNameBuilder,以及LdapUtils中的一些實用方法,這些方法有助於處理LdapName

示例

本節介紹前面章節中涵蓋主題的一些示例。第一個示例使用LdapNameBuilder動態構建LdapName

示例5. 使用LdapNameBuilder動態構建LdapName
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具有以下屬性

屬性名稱 屬性值

國家

瑞典

公司

某公司

全名

某人

前面的程式碼將生成以下判別名

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

以下示例使用LdapUtils從判別名中提取值

示例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;
  }
}

由於Java 1.4及以前版本根本沒有提供任何公共判別名實現,Spring LDAP 1.x提供了自己的實現,即DistinguishedName。此實現本身也存在一些缺點,並在2.0版本中已棄用。您現在應該使用LdapName以及前面描述的實用程式。

繫結和解綁

本節介紹如何新增和刪除資料。更新將在下一節中介紹。

新增資料

在Java LDAP中插入資料稱為繫結。這有點令人困惑,因為在LDAP術語中,“繫結”意味著完全不同的東西。JNDI繫結執行LDAP Add操作,將具有指定判別名的新條目與一組屬性關聯起來。以下示例使用LdapClient新增資料

示例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簡化屬性訪問和操作中所述。

刪除資料

在Java LDAP中刪除資料稱為解綁。JNDI解綁執行LDAP Delete操作,從LDAP樹中刪除與指定判別名關聯的條目。以下示例使用LdapClient刪除資料

示例8. 刪除資料
public class PersonRepoImpl implements PersonRepo {
   private LdapClient ldapClient;
   ...
   public void delete(Person p) {
      Name dn = buildDn(p);
      ldapClient.unbind(dn).execute();
   }
}

更新

在Java LDAP中,資料可以透過兩種方式修改:使用rebind或使用modifyAttributes

使用Rebind進行更新

rebind是一種粗略的資料修改方式。它基本上是先unbind,然後bind。以下示例呼叫LDAP的rebind

示例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進行更新

一種更復雜的資料修改方法是使用modifyAttributes。此操作接受一個明確的屬性修改陣列,並將其在特定條目上執行,如下所示

示例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();
   }
}

構建AttributesModificationItem陣列需要大量工作。然而,正如我們在使用DirContextAdapter簡化屬性訪問和操作中所述,Spring LDAP為簡化這些操作提供了更多幫助。

© . This site is unofficial and not affiliated with VMware.