基本的な使い方
このセクションでは、Spring LDAP の使用の基本について説明します。次の内容が含まれます。
AttributesMapper
を使用した検索とルックアップ
次の例では、AttributesMapper
(Javadoc) を使用して、すべての人物オブジェクトのすべての共通名のリストを作成します。
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
オブジェクトを返すように簡単に変更できることに注意してください。
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
オブジェクトの検索を示しています。
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 は、LDAP クエリを構築するための流れるような API を備えた LdapQueryBuilder
(Javadoc) を提供します。
ベース 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 とその関連クラスは、検索フィルター内の安全でない文字を適切にエスケープする機能も提供します。これにより、ユーザーがそのような文字を使用して不要な操作を LDAP 操作に挿入する「LDAP インジェクション」を防止できます。 |
LdapClient には、LDAP 検索を実行するためのオーバーロードされたメソッドが多数含まれています。これは、可能な限り多くの異なるユースケースとプログラミングスタイルの設定に対応するためです。ほとんどのユースケースでは、入力として LdapQuery を使用するメソッドを使用することをお勧めします。 |
AttributesMapper は、検索およびルックアップデータを処理するときに使用できる利用可能なコールバックインターフェースの 1 つにすぎません。代替については、DirContextAdapter による属性アクセスと操作の簡素化を参照してください。 |
LdapQueryBuilder
の詳細については、高度な LDAP クエリを参照してください。
識別名を動的に構築する
識別名 ( LdapName
(標準 Javadoc) (英語) ) の標準 Java 実装は、識別名の解析に関しては良好に機能します。ただし、実際に使用すると、この実装にはいくつかの欠点があります。
LdapName
実装は変更可能であり、ID を表すオブジェクトにはあまり適していません。変更可能な性質にもかかわらず、
LdapName
を使用して識別名を動的に構築または変更するための API は扱いにくいものです。インデックス付きまたは (特に) 名前付きコンポーネントの値を抽出するのも、少し厄介です。LdapName
の操作の多くは、チェック例外をスローします。通常、エラーが致命的であり、意味のある方法で修復できない状況では、try-catch
ステートメントが必要です。
識別名の操作を簡素化するために、Spring LDAP は LdapNameBuilder
(Javadoc) と、LdapName
を操作するときに役立つ LdapUtils
(Javadoc) の多数のユーティリティメソッドを提供します。
サンプル
このセクションでは、前のセクションで説明した内容の例をいくつか紹介します。最初の例では、LdapNameBuilder
を使用して LdapName
を動的に構築します。
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
を使用して識別名から値を抽出します。
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 バージョンではパブリック識別名の実装がまったく提供されなかったため、Spring LDAP 1.x は独自の実装である DistinguishedName
を提供しました。この実装にはいくつかの欠点があり、バージョン 2.0 で廃止されました。ここで、LdapName
を前述のユーティリティと共に使用する必要があります。
バインドとアンバインド
このセクションでは、データを追加および削除する方法について説明します。更新については、次のセクションで説明します。
データの追加
Java LDAP にデータを挿入することをバインディングと呼びます。LDAP 用語では、「バインド」はまったく別のものを意味するため、これはやや混乱します。JNDI バインドは LDAP 追加操作を実行し、指定された識別名を持つ新しいエントリを一連の属性に関連付けます。次の例では、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;
}
}
手動属性構築は — 退屈で冗長ですが — 多くの目的に十分です。ただし、DirContextAdapter
による属性アクセスと操作の簡素化に従って、バインド操作をさらに単純化できます。
データの削除
Java LDAP でのデータの削除は、バインド解除と呼ばれます。JNDI アンバインドは LDAP 削除操作を実行し、指定された識別名に関連付けられたエントリを LDAP ツリーから削除します。次の例では、LdapClient
を使用してデータを削除します。
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
を使用する方法の 2 つの方法でデータを変更できます。
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();
}
}
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
配列を構築するのは大変な作業です。ただし、DirContextAdapter
による属性アクセスと操作の簡素化で説明しているように、Spring LDAP はこれらの操作を簡素化するためのより多くのヘルプを提供します。