这个版本仍在开发中,目前尚未被认为是稳定的。要使用最新稳定版本,请使用 Spring LDAP 4.0.2spring-doc.cadn.net.cn

用户使用 Spring LDAP 的身份验证

基本认证

虽然 ContextSource 的核心功能是为 LdapClientLdapTemplate 提供 DirContext 实例,你也可以使用它来将用户认证到 LDAP 服务器。ContextSourcegetContext(principal, credentials) 方法正是如此。它根据 ContextSource 配置构造一个 DirContext 实例,并使用提供的 principal 和凭据来认证上下文。一个自定义的 authenticate 方法可能如下所示: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);
  }
}

The userDn supplied to the authenticate method needs to be the full DN of the user to authenticate (regardless of the base setting on the ContextSource). You typically need to perform an LDAP search based on (for example) the user name to get this DN. The following example shows how to do so: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 中包含提供此功能的 authenticate 方法。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