LECTURE 2 LDAP サーバに接続する

○ はじめに

LDAP クライアント作成の手始めとして、LDAP サーバへ接続することから始めましょう! 全ての LDAP クライアントプログラミングの基本事項ですので、しっかり理解しておいて下さい。

○ サンプルプログラム

LDAP サーバに接続し、切断するだけの単純なサンプルプログラム LDAPConnect.java です。このクラスが行う処理は

  • 指定された LDAP サーバに接続する
  • 指定されたユーザおよびパスワードで認証を行う
  • 認証されたかどうか確認する
  • LDAP サーバとの接続を切断する

の 4 つの処理です。JLDAP のクラスライブラリにクラスパスが通っていることを前堤として、javac LDAPConnect.java でコンパイルして下さい。コンパイルが終了したら、

java LDAPConnect [LDAPサーバ名/IPアドレス] [bindユーザのDN] [bindユーザのパスワード]

で実行です。特に例外が発生せず、正常に認証されれば

Connected to [LDAPサーバ名/IPアドレス]
Authenticated
Disconnected

の様な表示が得られます。例外が発生したり認証されていなかったりすると表示が変わりますが、その辺については以降のサンプルプログラムの説明などで理解していって下さい

なお、はじめに のページから全てのサンプルプログラムを固めた tar ボールをダウンロードすることもできます。

--- LDAPConnect.java ---

    1	import org.ietf.ldap.LDAPConnection;
    2	import org.ietf.ldap.LDAPException;
    3	
    4	
    5	/**
    6	 * 指定された LDAP サーバに接続し、認証状態を確認した後接続を切断するクラス。
    7	 *
    8	 * @version 19 May 2002
    9	 * @author  Ryo Ichinose
   10	 */
   11	public class LDAPConnect
   12	{
   13		/**
   14		 * LDAP Protocol Version 3
   15		 */
   16		public static final int LDAP_V3 = 3; // LDAPv3
   17	
   18	
   19		/**
   20		 * 指定された LDAP サーバに接続し、認証状態を確認した後切断する。
   21		 *
   22		 * @param host    ホスト名もしくは IPアドレス
   23		 * @param binddn  bind ユーザの DN
   24		 * @param bindpw  bind ユーザのパスワード
   25		 */
   26		public void connect( String host, String binddn, String bindpw )
   27		{
   28			LDAPConnection lc = new LDAPConnection();
   29	
   30			try {
   31				// LDAP サーバに接続する。ポートはデフォルト(389番)を使う。
   32				lc.connect( host, LDAPConnection.DEFAULT_PORT );
   33				System.out.println( "Connected to " + host );
   34	
   35	
   36				// 指定された DN およびパスワードでバインド(認証)する。
   37				// これを実行しない場合、anonymous 状態で操作することになる。
   38				lc.bind( LDAPConnect.LDAP_V3, binddn, bindpw );
   39	
   40	
   41				// LDAP サーバに認証されたかどうかを確認する。
   42				//
   43				// lc.bind() に間違ったパスワードを指定した場合、LDAPException
   44				// が throw されるが、その他の理由(期限切れなど)によって認証
   45				// されていない可能性もあるため、isBound() メソッドで確認する。
   46	
   47				if ( lc.isBound() ) {
   48					System.out.println( "Authenticated" );
   49				}
   50				else {
   51					System.out.println( "Not authenticated" );
   52				}
   53	
   54				// 接続を切断する。
   55				lc.disconnect();
   56				System.out.println( "Disconnected" );
   57			}
   58			catch( LDAPException e ) {
   59				System.out.println( "LDAPException occured : " + 
   60						    e.toString() );
   61			}
   62		}
   63	
   64	
   65		/**
   66		 * エントリポイント
   67		 *
   68		 * @param args 
   69		 *    <ul>
   70		 *      <li>args[0] --- ホスト名もしくは IP アドレス
   71		 *      <li>args[1] --- bind ユーザの DN
   72		 *      <li>args[2] --- bind ユーザのパスワード
   73		 *    </ul>
   74		 */
   75		public static void main( String[] args )
   76		{
   77			LDAPConnect obj = new LDAPConnect();
   78			obj.connect( args[0], args[1], args[2] );
   79		}
   80	}


○ サンプルプログラムの説明

では、サンプルプログラムについて説明していきます。

  • 1 〜 2 行目

    使用する JLDAP のクラスライブラリのパッケージ指定を行っています。org.ietf.ldap パッケージは、IETF のドラフトで記述されている LDAP 用 Java API を納めてあるパッケージ です。JLDAP では、IETF のドラフトに準拠したクラスライブラリの他に Novell 独自のクラス ライブラリを使用することが当然できます。が、本文書( および以降の文書 )においては基本的に org.ietf.ldap パッケージ内のクラスのみを使用します。これによって、他の Directory SDK との互換性を保つことを意識しています(実際にはパッケージ名は修正する必要があったりしますが)。

    LDAPConnect クラスでは、LDAPConnection および LDAPException の 2 つのクラスのみを使用します。

  • 19 〜 62 行目 ( LDAPConnect#connect() )

    LDAPConnect#connect() メソッドで、全ての処理を行います。各ヶ所について以降で説明します。

    • 28 行目

      LDAP API の全ての操作の基本となる LDAPConnection クラスのインスタンスを作成しています。 LDAPConnection クラスは、LDAP サーバへの接続、ディレクトリエントリの検索、追加、削除、 修正、その他様々なメソッドを持っています。最も頻繁に( というか必ず )使用するクラスで す。

    • 31 〜 33 行目

      LDAPConnection#connect() メソッドを使って LDAP サーバに接続しています。何らかの理由で 接続に失敗した場合、LDAPException が throw されます。

        public void LDAPConnection#connect( String host, int port )
           throws LDAPException
      
        host : LDAP サーバのホスト名、もしくは IP アドレス
        port : LDAP サーバに接続する際のポート番号。
               LDAP サービスのデフォルトポート番号は 389 番
      
      

      LDAPException がどのような理由で throw されたかを知る方法については後程説明します。

    • 36 〜 38 行目

      ディレクトリに対する操作を特定のユーザ権限で実行するために、bind() ( 認証 ) します。 bind() しない場合、anonymous 状態で操作を行うことになるので、LDAP サーバ側のアクセス 制御によって操作が不可能な場合があります。必要な権限を持ったユーザで bind() しないと いけません( anonymous でよければ bind() する必要はありません )。

          public void LDAPConnection#bind( int version, String dn, String passwd )
             throws LDAPException
      
          version : bind を実行する際に使用する LDAP のバージョン。LDAPv2 を使う場合は 2、
                    LDAPv3 を使う場合は 3 を指定
          dn      : bind するユーザの DN
          passwd  : bind するユーザのパスワード
      
      

      bind() に指定する dn および passwd が正しくない場合、LDAPException が throw されます。

      bind() メソッドは上の形式以外の形でいくつかオーバーロードされています。それぞれの詳 細については JLDAP の API ドキュメントを参照して下さい。

    • 41 〜 52 行目

      bind() で例外が発生しなかった場合でも、実際には認証されていない場合があり得ます(ユーザ のログイン期限切れなど)。正しく認証されているかどうか確認するには、 LDAPConnection#isBound() メソッドを使います。

        public boolean LDAPConnection#isBound()
      
      

      認証されていれば true、認証されていなければ false を返します。

    • 54 〜 56 行目

      LDAP サーバとの接続を切断します。

        public void LDAPConnection#disconnect()
           throws LDAPException
      
      

      disconnect() メソッドは上の形式以外の形でオーバーロードされています。詳細については JLDAP の API ドキュメントを参照して下さい。

    • 58 〜 61 行目

      これまでの処理で throw される可能性のある LDAPException を catch しています。ここで は LDAPException#toString() で例外の内容を表示させているだけですが、例外の内容に応じ て処理を変えたい場合もあると思います。

      JLDAP では、LDAP に関する全ての例外は LDAPException として throw されますが、例外の 内容に応じてエラーコードが設定されています。エラーコードを取りだすには LDAPException#getLDAPResultCode() メソッドを使用します。

        public int LDAPException#getLDAPResultCode()
      
      

      エラーコードの値がどのような内容を示しているのかについては、JLDAP API ドキュメントに 記述されているので、詳細はそちらを参照して下さい。なお、LDAPConnect クラスにおける処 理で発生する可能性のある例外内容について、自分が確認できた範囲で以下にまとめておきま す。これで全てという意味ではありませんm(__)m。

      なお、ここで発生する例外は以降の全てのサンプルプログラムで同じ条件で発生します (同じ ことをやってるから)。

      番号 エラーコードの定数名(LDAPException.XXX の形で参照可) 内容
      2 PROTOCOL_ERROR LDAP サーバがクライアントから不正な要求を受け取った。LDAPConnect.java の場合、bind() に不正な LDAP バージョンを指定すると発生する。
      48 INAPPROPRIATE_AUTHENTICATION LDAP クライアントが正しく処理できない認証方法で bind() を試みている。と API ドキュメントに書かれているが、LDAPConnect クラスの場合、LDAP サーバにおいて userPassword 属性が定義されていないエントリをユーザとして bind() する際に パスワードを指定すると生じる。
      49 INVALID_CREDENTIALS bind() による認証時に誤った情報を指定している。不正な bind ユーザ、もしくは bind パスワードを指定した際に生じる可能性。
      91 CONNECT_ERROR 接続失敗。あるいは確立したはずの接続が切断されている。LDAPConnection#connect() でサーバ指定あるいはポート指定を誤った場合に生じる可能性。

以上で LDAPConnect.java についての説明は終わりです。次は、ディレクトリエントリの登録/削除の方法を紹介します。