此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring LDAP 3.3.3spring-doc.cadn.net.cn

使用 Spring LDAP 进行用户身份验证

基本身份验证

虽然ContextSource就是提供DirContextLdapClientLdapTemplate,您还可以使用它来针对 LDAP 服务器对用户进行身份验证。这getContext(principal, credentials)方法ContextSource正是这样做的。它构造了一个DirContext实例根据ContextSource配置并使用提供的主体和凭据对上下文进行身份验证。自定义身份验证方法可能类似于以下示例:spring-doc.cadn.net.cn

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);
  }
}

userDn提供给authenticate方法需要是要进行身份验证的用户的完整 DN(无论baseContextSource).您通常需要根据(例如)用户名执行 LDAP 搜索才能获取此 DN。以下示例显示了如何执行此作:spring-doc.cadn.net.cn

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提供此功能。spring-doc.cadn.net.cn

使用此方法时,身份验证变得简单,如下所示:spring-doc.cadn.net.cn

示例 1.使用 Spring LDAP 对用户进行身份验证
ldapClient.authenticate().query(query().where("uid").is("john.doe")).password("secret").execute();
如对已验证上下文执行作中所述,某些设置可能需要执行其他作才能进行实际身份验证。有关详细信息,请参阅对已验证的上下文执行作
不要编写自己的自定义身份验证方法。使用 Spring LDAP 中提供的那些。

对已验证的上下文执行作

某些身份验证方案和 LDAP 服务器需要对创建的DirContext实例进行实际身份验证。您应该测试并确保服务器设置和身份验证方案的行为方式。否则,无论提供的 DN 和凭证如何,都可能导致用户被允许进入您的系统。以下示例显示了 authenticate 方法的朴素实现,其中硬编码的lookup作在经过身份验证的上下文上执行:spring-doc.cadn.net.cn

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方法。spring-doc.cadn.net.cn

此方法允许对经过身份验证的上下文执行任何作,如下所示:spring-doc.cadn.net.cn

示例 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-doc.cadn.net.cn

使用 Spring Security

虽然前几节中所述的方法可能足以满足简单的身份验证方案,但此领域的要求通常会迅速扩展。许多方面都适用,包括身份验证、授权、Web 集成、用户上下文管理等。如果您怀疑要求可能会扩展到简单的身份验证之外,您绝对应该考虑将 Spring Security 用于您的安全目的。它是一个功能齐全、成熟的安全框架,解决了上述方面以及其他几个方面。spring-doc.cadn.net.cn