1

我使用带有 Spring Boot 的 Spring Security 进行了成功的配置,它将检查四个不同的 LDAP 提供程序以获取传递给它的用户凭据。如果用户不在第一台服务器中,则检查第二台服务器,依此类推。如果所有提供程序都可用,这将非常有效。但是,如果其中一个提供程序关闭,则身份验证链停止并且 spring 返回一个未经授权的异常。

身份验证适用于基于 REST 的服务,因此使用故障处理程序重定向到不同的 URL 似乎对这种情况没有帮助。

我知道上下文源上的 urls 属性,但据我所知,它仅用于故障转移到与主 LDAP 服务器具有相同配置的镜像 LDAP 服务器。在此配置中并非如此,每个 LDAP 服务器都有自己独立且不同的配置。

我检查了多个 StackOverflow 问题以及 Spring 文档和存档论坛。我看到的所有问题和配置要么是针对镜像故障转移配置,要么与我的配置基本相同。

我当前的配置和 AuthenticationManager 设置是通过 Groovy 类配置的,如下所示:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .anyRequest().authenticated()                                                   
            .and()
        .httpBasic()

    http.httpBasic().realmName("Service Authorization")
}


@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {

    authManagerBuilder.ldapAuthentication()
        .userSearchFilter("${ldapExtConfig.userSearchFilter}")
        .contextSource().url("${ldapExtConfig.url}/${ldapExtConfig.baseDn}")
        .managerDn("${ldapExtConfig.managerDn}")
        .managerPassword("${ldapExtConfig.managerPassword}")

    authManagerBuilder.ldapAuthentication()
        .userSearchFilter("${ldapAmerConfig.userSearchFilter}")
        .contextSource().url("${ldapAmerConfig.url}/${ldapAmerConfig.baseDn}")
            .managerDn("${ldapAmerConfig.managerDn}")
            .managerPassword("${ldapAmerConfig.managerPassword}")

    authManagerBuilder.ldapAuthentication()
        .userSearchFilter("${ldapEmeaConfig.userSearchFilter}")
        .contextSource().url("${ldapEmeaConfig.url}/${ldapEmeaConfig.baseDn}")
        .managerDn("${ldapEmeaConfig.managerDn}")
        .managerPassword("${ldapEmeaConfig.managerPassword}")

    authManagerBuilder.ldapAuthentication()
        .userSearchFilter("${ldapApacConfig.userSearchFilter}")
        .contextSource().url("${ldapApacConfig.url}/${ldapApacConfig.baseDn}")
        .managerDn("${ldapApacConfig.managerDn}")
        .managerPassword("${ldapApacConfig.managerPassword}")

}

我可以将其拆分为多个 war/jar 文件,因为 Spring Boot 是轻量级的,但该解决方案被服务器管理器拒绝。我是否必须考虑实现自定义身份验证提供程序并尝试包装尝试序列?

如果第一个无法连接,是否有任何方法可以配置 Spring Security 以继续尝试后续的 AuthenticationProviders?我认为这应该是可能的,否则能够指定多种类型的提供者的效用是有限的。谢谢!

更新:我已经做了一些工作来在本地复制它,但我无法让它像我认为的那样工作。即使将 Spring Security 日志记录设置为 DEBUG,我也无法收到日志消息。我能够在返回给我的 JSON 响应中获得一些额外的信息。下面的消息中故意更改了主机名。

{
  "error": "Unauthorized",
  "message": "ldapserver:636; nested exception is javax.naming.CommunicationException: ldapserver:636 [Root exception is java.net.UnknownHostException: ldapserver]",
  "status": 401,
  "timestamp": 1404924353023
}

因此,似乎正在发生的是 Spring Security LDAP 提供程序正在包装通信异常,而不是记录它,并自动将其转换为未经授权的异常。这不是我预期的行为,特别是因为我在配置中指定了多个提供程序。

更新 2:我知道上面说的是未知主机异常。我故意为第一台服务器输入了不正确的主机名,以获得通信类型的异常。当网络在测试期间暂时无法访问服务器时,也会发生相同类型的事情。

4

0 回答 0