JavaでLDAP認証する方法

JavaでLDAP認証する方法です。

JavaでLDAP認証する方法

企業の社内システムでは、LDAPを使って認証をおこなっているケースがあります。今回、初めてLDAP認証システムへ関わる機会があったのでテストソースを残しておきます。

javax.namingパッケージを使えば割と簡単にLDAP認証ができますよ。

ここでは JavaでLDAP認証する方法 を紹介します。


LDAPの属性値を理解する

LDAPの属性値は企業によって設定が様々です。当然ですが、ディレクトリサービスにどのような定義がされているかは事前に確認が必要です。

LDAPの
属性値
属性表示名オブジェクトタイプ
cnCommon-Nameユーザー名、グループ名、コンピュータ名、コンテナ名
ouOrganizational-Unit-Name組織単位
dcDomain-Componentドメイン

例えば、ドメイン「saka-en.com」の組織「developers」に配置したユーザー「Ken」は以下のように示されます。

cn=Ken, ou=developers, dc=saka-en, dc=com

この辺りは、検索すれば詳しく説明してくれているサイトがたくさんあるので、事前に調査しておきましょう。

JavaでLDAP認証する

JavaでLDAP認証するポイントは2つです。

  • LDAPサーバーへ接続する。
  • ID/パスワード使用してユーザー認証する。

認証OKなら取得できた情報をコンソールへ出力し、認証NGならエラーメッセージをコンソールへ表示してみましょう。

テストコードはこうなります。

package ldaptest;

import java.util.Hashtable;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

public class LdapTest {

  /**
   * LDAP 認証テスト
   */
  public static void main(String[] args) throws NamingException {

      // LDAP接続情報
      Hashtable<String, String> env = new Hashtable<>();
      env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
      env.put(Context.PROVIDER_URL, "ldap://localhost:389"); // LDAPサーバー
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
      env.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=systems,o=group"); // ID, 組織
      env.put(Context.SECURITY_CREDENTIALS, "secret"); // パスワード

      // 認証したいID・パスワード
      String userId = "user001";
      String password = "p@ss001";

      DirContext ctx = new InitialDirContext(env);
      try {
          SearchControls searchControls = new SearchControls();
          searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
          NamingEnumeration<SearchResult> searchResult = ctx.search("", "uid=" + userId, searchControls);
          Attributes attrs = (Attributes)searchResult.nextElement().getAttributes();
          System.out.println(attrs.toString());
          Hashtable<String, String> uenv = new Hashtable<>(env);
          uenv.put(Context.SECURITY_PRINCIPAL, "cn=" + cn + ", ou=staff, o=company, o=group");
          uenv.put(Context.SECURITY_CREDENTIALS, password);

          DirContext uctx = new InitialDirContext(uenv);
          uctx.close();

          System.out.println("認証OK");
      } catch (AuthenticationException e) {
        System.out.println("ユーザーID、パスワードが違います。");
      } catch (Exception e) {
        System.out.println("ユーザーID、パスワードが違います。");
     } finally {
          ctx.close();
      }
  }
}

認証が失敗すると AuthenticationException が発生します。例外が発生しなければ認証OKとなります。

認証が失敗する場合の対処方法

LDAPサーバーへは接続できている、ユーザーIDもパスワードも一致しているのに認証が失敗する場合には、下記のコードを実行してみてください。

while (searchResult != null && searchResult.hasMore()) {
  SearchResult si = (SearchResult)searchResult.next();
  // エントリ名の出力
  System.out.println("name: " + si.getName());
  Attributes attrs = si.getAttributes();
  if (attrs == null)
    System.out.println("No attributes");
  else {
    // 属性の出力
    for (NamingEnumeration<?> ae = attrs.getAll();
      ae.hasMoreElements(); ) {
        Attribute attr = (Attribute)ae.next();
        String attrId = attr.getID();
        // 属性値の出力
        for (Enumeration<?> vals = attr.getAll();
          vals.hasMoreElements();
          System.out.println(attrId + ": " + vals.nextElement()));
     }
  }
  System.out.println();
}

多くの場合、属性の設定ミスや属性値の違いなどによるものだと思うので、出力結果をよく見て調整してみてください。

まとめ

JavaでLDAP認証する方法を紹介しました。

思ったより簡単にLDAP認証ができてよかったです。ハマる要素があるとすればLDAPの属性値の組み立てでしょうかね。

皆さんも試してみてください。

おつかれさまでした。

この記事がお役に立ちましたら シェア をお願いいたします。