SpringLDAPでディレクトリアクセスを簡素化する

Spring LDAPは、JavaプラットフォームでのLDAPプログラミングを簡素化するSpringベースのフレームワークです。Spring LDAPの使用に関するこのステップバイステップガイドでは、フレームワークがほとんどのLDAPクライアントに必要な低レベルのコーディングを処理する方法を学習し、アプリケーションのビジネスロジックの開発に集中できるようにします。また、Spring LDAPを使用して簡単なCRUD操作を練習し、動的フィルターの作成やLDAPエントリのJavaBeanへの変換などのより高度な操作について学習します。

ライトウェイトディレクトリアクセスプロトコルは、今日のほとんどの大規模なエンタープライズアプリケーション展開の重要なコンポーネントです。 LDAPは主に、ユーザーのユーザー名、パスワード、電子メールアドレスなどのユーザーIDに関連する情報を格納するために使用されます。また、認証と承認の目的でユーザーアクセス権を保存する必要があるセキュリティ実装でも使用されます。

Java Naming and Directory Interface(JDNI)は、JavaプラットフォームでのLDAPプログラミングに使用されるAPIです。これは、アプリケーション内でLDAPサーバーと対話するために使用できる標準インターフェースを定義します。残念ながら、JNDIを使用するには、通常、低レベルの反復コードを多数作成する必要があります。 JNDIは、リソースが適切に開閉されていることを確認するなど、単純な手順で非常に多くの作業を行います。さらに、ほとんどのJNDIメソッドは、処理に時間がかかるチェック済み例外をスローします。よく調べてみると、JNDIのプログラミングに費やされた時間の50〜60%が、反復的なタスクの処理に浪費されているようです。

Spring LDAPは、JavaプラットフォームでのLDAPプログラミングを簡素化するように設計されたオープンソースのJavaライブラリです。Spring FrameworkがJavaエンタープライズアプリケーション開発から低レベルプログラミングの多くを取り除くように、SpringLDAPはLDAPの使用に関するインフラストラクチャの詳細から解放されます。を心配してNamingException取得するInitialContextのではなく、アプリケーションのビジネスロジックに自由に集中できます。Spring LDAPはまた、包括的な未チェックの例外階層を定義し、LDAPフィルターと識別名を構築するためのヘルパークラスを提供します。

SpringLDAPとJNDI

SpringLDAPフレームワークはJNDIに置き換わるものではないことに注意してください。むしろ、JavaプラットフォームでのLDAPプログラミングを簡素化するために、JNDIを介してラッパークラスとユーティリティクラスを提供します。

この記事、Spring LDAPの使用に関する初心者向けガイドでは、LDAP検索を実行するための簡単なJNDIプログラムを開発することから始めます。次に、SpringLDAPフレームワークを使用して同じことを行うのがどれほど簡単かを示します。Spring LDAPを使用してAttributeMapperLDAP属性をJavaBeanにマップする方法と、その動的フィルターを使用してクエリを作成する方法を示します。最後に、Spring LDAPフレームワークを使用してLDAPサーバーのデータを追加、削除、および変更する方法を段階的に紹介します。

この記事は、SpringFrameworkの概念と用語に精通していることを前提としていることに注意してください。Spring Framework、LDAP、およびJNDIの詳細と、サンプルアプリケーションのダウンロードについては、「リソース」セクションを参照してください。

単純なJNDIクライアント

リスト1は、コンソール上のすべてのタイプ・オブジェクトのcn属性を出力する単純なJNDIプログラムを示しPersonています。

リスト1.SimpleLDAPClient.java

public class SimpleLDAPClient { public static void main(String[] args) { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:10389/ou=system"); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system"); env.put(Context.SECURITY_CREDENTIALS, "secret"); DirContext ctx = null; NamingEnumeration results = null; try { ctx = new InitialDirContext(env); SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); results = ctx.search("", "(objectclass=person)", controls); while (results.hasMore()) { SearchResult searchResult = (SearchResult) results.next(); Attributes attributes = searchResult.getAttributes(); Attribute attr = attributes.get("cn"); String cn = (String) attr.get(); System.out.println(" Person Common Name = " + cn); } } catch (NamingException e) { throw new RuntimeException(e); } finally { if (results != null) { try { results.close(); } catch (Exception e) { } } if (ctx != null) { try { ctx.close(); } catch (Exception e) { } } } } }

リスト1で最初に行ったことは、InitialDirContextオブジェクトを作成することです。このオブジェクトは、次のディレクトリ操作のコンテキストとして使用されます。新しいContextオブジェクトを作成するときに、LDAPサーバーへの接続に使用できるユーザー名、パスワード、認証メカニズムなどのプロパティを構成します。これを管理するには、Hashtableオブジェクトを作成し、これらすべてのプロパティをキーと値のペアとして設定し、コンストラクターにHashtable渡します。HashtableInitialDirContext

このアプローチの当面の問題は、すべての構成パラメーターを.javaファイルにハードコーディングしたことです。これは私の例では問題なく機能しますが、実際のアプリケーションでは機能しません。実際のアプリケーションでは、接続プロパティをjndi.propertiesファイルに保存し、そのファイルをプロジェクトのクラスパスまたは/ libフォルダーに配置します。新しいInitialDirContextオブジェクトを作成すると、JNDI APIは両方の場所でjndi.propertiesファイルを探し、それを使用してLDAPサーバーへの接続を作成します。

JNDI構成パラメーター

リスト2は、LDAPサーバーに接続するためのJNDI構成パラメーターを示しています。以下にパラメータの意味を説明します。

リスト2.LDAPのJNDI構成パラメーター

java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory java.naming.provider.url=ldap://localhost:10389/ou=system java.naming.security.authentication=simple java.naming.security.principal=uid=admin,ou=system java.naming.security.credentials=secret
  1. Context.INITIAL_CONTEXT_FACTORYjava.naming.factory.initial)は、新しい初期コンテキストの作成に使用される完全修飾クラス名と同じである必要があります。値が指定されていない場合は、NoInitialContextExceptionがスローされます。
  2. Context.PROVIDER_URLjava.naming.provider.url)は、接続するLDAPサーバーのURLと同じである必要があります。の形式である必要がありますldap://:
  3. Context.SECURITY_AUTHENTICATIONjava.naming.security.authentication)は、使用する認証メカニズムのタイプを表します。この例では認証にユーザー名とパスワードを使用したので、このプロパティの値は単純です。
  4. Context.SECURITY_PRINCIPALjava.naming.security.principal)は、接続を確立するために使用する必要がある識別されたユーザー名(DN)を表します。
  5. Context.SECURITY_CREDENTIALSjava.naming.security.credentials)は、ユーザーのパスワードを表します。

JNDIクライアントコード

Contextオブジェクトを取得したら、次のステップはSearchControlオブジェクトを作成することです。オブジェクトは、検索の範囲と返されるものを決定する要素をカプセル化します。コンテキストをルートとするサブツリー全体を検索したいので、リスト1に示したように、SUBTREE_SCOPEsetSearchScope()メソッドを呼び出して検索範囲をに設定しますSearchControl

次に、のsearch()メソッドを呼び出し、フィルターの値としてDirContext渡し(objectclass=person)ます。このsearch()メソッドはNamingEnumeration、のサブツリー内のすべてのエントリを含むオブジェクトを返します。Contextここで、はobjectclassですpersonNamingEnumeration結果オブジェクトとしてを取得した後、それを繰り返し処理し、各オブジェクトのcn属性を出力しPersonます。

これで、JNDIクライアントコードの説明は終わりです。リスト1に示すSimpleLDAPClient.javaを見ると、コードの半分以上がリソースの開閉に向けられていることが簡単にわかります。JNDI APIのもう1つの問題NamingExceptionは、エラーが発生した場合に、ほとんどのメソッドがそのサブクラスの1つまたは1つをスローすることです。NamingExceptionはチェックされた例外であるため、スローされた場合は処理する必要がありますが、LDAPサーバーがダウンした場合、本当に例外から回復できますか?いいえ、できません。

ほとんどの開発者は、JNDIをNamingExceptionキャッチして何もしないことで、JNDIを回避します。このソリューションの問題は、重要な情報が失われる可能性があることです。