2013年4月28日日曜日

AD 情報取得のための Java プログラム

前回は AD 認証を行うサンプルを紹介しましたが、今回は AD から情報を取り出すサンプルを紹介します。AD にはいろいろな情報がありますが、今回はユーザの名前、アカウントID、メールアドレスを抽出するプログラムを紹介します。

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.AuthenticationException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchResult;
import javax.naming.directory.SearchControls;

/**
 * JNDI の LDAP インタフェースを用いて AD からユーザ情報を取得
 *
 * 引数1:AD 接続先 URL
 * 引数2:AD のドメイン名
 * 引数3:ユーザID(AD が参照できる Administrator 等)
 * 引数4:パスワード
 * 引数5:検索先のルートとなる DN
 * 引数6:抽出する属性のリスト(カンマ区切り)。
 *     userPrincipalNameLocal ⇒ アカウントID(ドメインを含まない)を出力
 */
public class adlist {

    public static void main(String args[]) throws NamingException {

        Hashtable env = new Hashtable();

        // Contextファクトリ
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");

        // 接続先URL
        env.put(Context.PROVIDER_URL,args[0]);

        // セキュリティレベル
        env.put(Context.SECURITY_AUTHENTICATION, "simple");

        // ユーザID+ドメイン
        env.put(Context.SECURITY_PRINCIPAL, args[2] + "@" + args[1]);

        // パスワード
        env.put(Context.SECURITY_CREDENTIALS, args[3]);

try {
           // AD に接続
           InitialDirContext context = new InitialDirContext(env);

// 指定されたルート DN 以下のユーザを検索
  String base = args[4];
  String filter = "CN=*";
  SearchControls controls = new SearchControls();
  controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
  NamingEnumeration answer = context.search(base, filter, controls);

  // 引数の抽出属性リストを分解
  String[] cols = args[5].split(",");
  int colSize = cols.length;

  // 検索結果のループ
  while ( answer.hasMore() ) {
    SearchResult result = (SearchResult)answer.next();
      Attributes attr = result.getAttributes();
      for ( int i = 0; i < colSize; i++ ) {
        if ( cols[i].startsWith("userPrincipalNameLocal") ) {
          // アカウントID(ドメインを含まない)を出力
        String name = attr.get("userPrincipalName").get().toString();
        name = name.substring(0, name.indexOf("@"));
        System.out.print(name);
        } else {
        // 指定された属性を出力
        if ( attr.get(cols[i]) != null ) {
          System.out.print(attr.get(cols[i]).get().toString());
        }
        }
      if ( i != colSize -1 ) {
      System.out.print(",");
        }
       }
      System.out.println();
     }
    } catch (AuthenticationException ex) {
    // 認証エラー
    System.out.println("認証エラー");
  } catch (NamingException ex ) {
    // その他通信エラー等
    ex.printStackTrace();
  }
    }
}


このプログラムは、以下のようにパラメータを渡して利用することができます。


set PARAM=ldap://XXX.XXX.XXX.XXX:389/
set PARAM=%PARAM% mypcad.com
set PARAM=%PARAM% Administrator
set PARAM=%PARAM% "mypassword"
set PARAM=%PARAM% "OU=NAMELESS,DC=my0000ad,DC=mypcad,DC=com"
set PARAM=%PARAM% cn,displayName,userPrincipalNameLocal,mail

java adlist %PARAM%


第5引数は、検索のルートとなる OU の DN を指定します。正しい DN を調べるには、以下のコマンドを利用します。

dsquery user -name NAMELESS

第6引数には、取得したい AD の属性をカンマ区切りで指定します。AD がどのような属性を持つかは、以下のサイトが参考になります。

http://support.microsoft.com/kb/257218/ja

プログラムでは、属性に userPrincipalNameLocal を指定した場合に、ユーザー プリンシパル名(accountid@domain のような情報)からアカウントIDのみを取り出して表示するように工夫しています。

意外と簡単にできますね。


0 コメント:

コメントを投稿