此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring LDAP 3.2.8! |
使用 Spring LDAP 进行用户认证
本节介绍使用 Spring LDAP 进行用户身份验证。它包含以下主题:
基本身份验证
虽然 的核心功能是提供实例供 和 使用,但您也可以使用它根据 LDAP 服务器对用户进行身份验证。的方法正是这样做的。它根据配置构造一个实例,并使用提供的主体和凭据对上下文进行身份验证。自定义身份验证方法可能类似于以下示例:ContextSource
DirContext
LdapClient
LdapTemplate
getContext(principal, credentials)
ContextSource
DirContext
ContextSource
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);
}
}
提供给方法的 DN 必须是要进行身份验证的用户的完整 DN(无论 上的设置如何)。通常需要根据用户名(例如)执行 LDAP 搜索才能获取此 DN。以下示例显示了如何执行此操作:userDn
authenticate
base
ContextSource
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
当您使用此方法时,身份验证将变得如此简单,如下所示:
ldapClient.authenticate().query(query().where("uid").is("john.doe")).password("secret").execute();
如在已验证的上下文中执行操作中所述,某些设置可能需要您执行其他操作才能进行实际验证。有关详细信息,请参阅对 Authenticated Context 执行操作。 |
不要编写自己的自定义身份验证方法。使用 Spring LDAP 中提供的那些。 |
对已验证的上下文执行操作
某些身份验证方案和 LDAP 服务器需要在创建的实例上执行一些操作,以便进行实际身份验证。您应该测试并确保服务器设置和身份验证方案的行为方式。如果不这样做,可能会导致用户被允许进入您的系统,而不管提供的 DN 和凭证如何。以下示例显示了 authenticate 方法的朴素实现,其中对经过身份验证的上下文执行硬编码操作:DirContext
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);
}
}
如果该操作可以作为回调接口的实现提供,而不是将操作限制为始终为 .Spring LDAP 包括回调接口和相应的方法。lookup
AuthenticatedLdapEntryContextMapper
authenticate
此方法允许在经过身份验证的上下文中执行任何操作,如下所示:
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);
使用 Spring Security
虽然前面部分中描述的方法可能足以满足简单的身份验证方案,但此领域的要求通常会迅速扩展。适用许多方面,包括身份验证、授权、Web 集成、用户上下文管理等。如果您怀疑这些要求可能超出简单的身份验证范围,那么您绝对应该考虑使用 Spring Security 来实现您的安全目的。它是一个功能齐全、成熟的安全框架,可解决上述方面以及其他几个方面。