Spring LDAP を使用したユーザー認証

このセクションでは、Spring LDAP を使用したユーザー認証について説明します。次のトピックが含まれています。

基本認証

ContextSource の中心的な機能は、LdapClient および LdapTemplate で使用する DirContext インスタンスを提供することですが、LDAP サーバーに対するユーザーの認証にも使用できます。ContextSource の getContext(principal, credentials) メソッドはまさにそれを行います。ContextSource 構成に従って DirContext インスタンスを構築し、提供されたプリンシパルと資格情報を使用してコンテキストを認証します。カスタム認証メソッドは次の例のようになります。

public boolean authenticate(String userDn, String credentials) {
  DirContext ctx = null;
  try {
    ctx = contextSource.getContext(userDn, credentials);
    return true;
  } catch (Exception e) {
    // Context creation failed - authentication did not succeed
    logger.error("Login failed", e);
    return false;
  } finally {
    // It is imperative that the created DirContext instance is always closed
    LdapUtils.closeContext(ctx);
  }
}

authenticate メソッドに提供される userDn は、認証するユーザーの完全な DN である必要があります ( ContextSource の base 設定に関係なく)。通常、この DN を取得するには、(たとえば) ユーザー名に基づいて LDAP 検索を実行する必要があります。次の例は、その方法を示しています。

private String getDnForUser(String uid) {
  List<String> result = ldapClient.search()
      .query(query().where("uid").is(uid))
      .toList((Object ctx) -> ((DirContextOperations) ctx).getNameInNamespace());

  if(result.size() != 1) {
    throw new RuntimeException("User not found or not unique");
  }

  return result.get(0);
}

このアプローチにはいくつかの欠点があります。ユーザーの DN を考慮する必要があり、検索できるのはユーザーの uid だけであり、検索は常にツリーのルート (空のパス) から始まります。より柔軟な方法では、検索ベース、検索フィルター、資格情報を指定できます。Spring LDAP には、この機能を提供する LdapClient の認証メソッドが含まれています。

この方法を使用すると、認証は次のように簡単になります。

例 1: Spring LDAP を使用したユーザーの認証
ldapClient.authenticate().query(query().where("uid").is("john.doe")).password("secret").execute();
認証されたコンテキストでの操作の実行に従って、セットアップによっては、実際の認証を行うために追加の操作を実行する必要がある場合があります。詳細については、認証されたコンテキストでの操作の実行を参照してください。
独自のカスタム認証メソッドを作成しないでください。Spring LDAP で提供されているものを使用してください。

認証されたコンテキストでの操作の実行

一部の認証スキームおよび LDAP サーバーでは、実際の認証を行うために、作成された DirContext インスタンスに対して何らかの操作を実行する必要があります。サーバーのセットアップと認証スキームがどのように動作するかをテストして確認する必要があります。そうしないと、提供された DN と資格情報に関係なく、ユーザーがシステムに入ることが許可される可能性があります。次の例は、認証されたコンテキストでハードコードされた lookup 操作が実行される、認証メソッドの単純な実装を示しています。

public boolean myAuthenticate(String userDn, String credentials) {
  DirContext ctx = null;
  try {
    ctx = contextSource.getContext(userDn, credentials);
    // Take care here - if a base was specified on the ContextSource
    // that needs to be removed from the user DN for the lookup to succeed.
    ctx.lookup(userDn);
    return true;
  } catch (Exception e) {
    // Context creation failed - authentication did not succeed
    logger.error("Login failed", e);
    return false;
  } finally {
    // It is imperative that the created DirContext instance is always closed
    LdapUtils.closeContext(ctx);
  }
}

操作を常に lookup に制限するのではなく、コールバックインターフェースの実装として操作を提供できれば良いでしょう。Spring LDAP には、AuthenticatedLdapEntryContextMapper コールバックインターフェースと、対応する authenticate メソッドが含まれています。

このメソッドを使用すると、次のように、認証されたコンテキストで任意の操作を実行できます。

例 2: Spring LDAP を使用した認証済みコンテキストでの LDAP 操作の実行
AuthenticatedLdapEntryContextMapper<DirContextOperations> mapper = new AuthenticatedLdapEntryContextMapper<DirContextOperations>() {
  public DirContextOperations mapWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification) {
    try {
      return (DirContextOperations) ctx.lookup(ldapEntryIdentification.getRelativeName());
    }
    catch (NamingException e) {
      throw new RuntimeException("Failed to lookup " + ldapEntryIdentification.getRelativeName(), e);
    }
  }
};

ldapClient.authenticate().query(query().where("uid").is("john.doe")).password("secret").execute(mapper);

廃止された認証方法

前のセクションで説明した authenticate メソッドに加えて、非推奨の認証メソッドを多数使用できます。これらは正常に機能しますが、代わりに LdapQuery メソッドを使用することをお勧めします。

Spring Security の使用

前のセクションで説明したアプローチは単純な認証シナリオには十分かもしれませんが、この分野の要件は一般に急速に拡大します。認証、認可、Web 統合、ユーザーコンテキスト管理など、さまざまな側面が適用されます。要件が単純な認証を超えて拡大する可能性があると思われる場合は、代わりにセキュリティ目的で Spring Security を使用することを検討する必要があります。これは、前述の側面だけでなく他のいくつかの側面にも対処する、完全な機能を備えた成熟したセキュリティフレームワークです。