Spring LDAP を使用したユーザー認証
This section covers user authentication with Spring LDAP. It contains the following topics:
基本認証
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))
.map((Object ctx) -> ((DirContextOperations) ctx).getNameInNamespace()).list();
if(result.size() != 1) {
throw new RuntimeException("User not found or not unique");
}
return result.get(0);
}There are some drawbacks to this approach. You are forced to concern yourself with the DN of the user, you can search only for the user’s uid, and the search always starts at the root of the tree (the empty path). A more flexible method would let you specify the search base, the search filter, and the credentials. Spring LDAP includes an authenticate method in LdapClient that provides this functionality.
この方法を使用すると、認証は次のように簡単になります。
ldapClient.authenticate().query(query().where("uid").is("john.doe")).password("secret").execute();| 認証されたコンテキストでの操作の実行に従って、セットアップによっては、実際の認証を行うために追加の操作を実行する必要がある場合があります。詳細については、認証されたコンテキストでの操作の実行を参照してください。 |
| Do not write your own custom authenticate methods. Use the ones provided in 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);
}
}It would be better if the operation could be provided as an implementation of a callback interface, rather than limiting the operation to always be a lookup. Spring LDAP includes the AuthenticatedLdapEntryContextMapper callback interface and a corresponding authenticate method.
このメソッドを使用すると、次のように、認証されたコンテキストで任意の操作を実行できます。
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 を使用することを検討する必要があります。これは、前述の側面だけでなく他のいくつかの側面にも対処する、完全な機能を備えた成熟したセキュリティフレームワークです。