如何让 Spring Boot Actuator LdapHealthIndicator 与 Spring Security 的 Ldap 一起运行?

Posted

技术标签:

【中文标题】如何让 Spring Boot Actuator LdapHealthIndicator 与 Spring Security 的 Ldap 一起运行?【英文标题】:How to get Spring Boot Actuator LdapHealthIndicator running with Ldap from Spring Security? 【发布时间】:2020-10-29 05:53:54 【问题描述】:

我正在使用 spring security 开发一个 spring boot 2.3 应用程序。身份验证和授权是通过 Spring Security 针对 AD 完成的。所以我正在使用 spring-security-ldap 和以下代码。

public class SecurityConfiguration extends WebSecurityConfigurerAdapter  
...
    public AuthenticationProvider adAuthenticationProvider() 

        ActiveDirectoryLdapAuthenticationProvider adProvider =
            new ActiveDirectoryLdapAuthenticationProvider(ldapDomain, ldapUrl);
        adProvider.setSearchFilter(ldapSearchFilter);

        adProvider.setAuthoritiesMapper(authorities -> 
            Collection<GrantedAuthority> gaCollection = new ArrayList<>();
            for (GrantedAuthority authority : authorities) 
                if ("admin".equals(authority.getAuthority())) 
                    gaCollection.add(new SimpleGrantedAuthority(Role.ADMIN));
                
            
            return gaCollection;
        );
        return adProvider;
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 

        auth.authenticationProvider(adAuthenticationProvider());
        auth.eraseCredentials(false);
    


相关的依赖应该是这样的:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>$spring-boot.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
...
    </dependencyManagement>

    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-juli</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-ldap</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- End Spring -->
...
    </dependencies>

这很好用。

现在我决定通过 spring-boot-starter-actuator 依赖项使用 Spring Boot Actuators 进行应用程序监控。

通过自动配置,它会检测我的数据源和 LdapHealthIndicator 的执行器。数据源正常时,LdapHealthIndicator 总是报如下错误。

CONDITIONS EVALUATION REPORT (only LDAP lines)

positive matches:
   LdapAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.ldap.core.ContextSource' (OnClassCondition)

   LdapAutoConfiguration#ldapContextSource matched:
      - @ConditionalOnMissingBean (types: org.springframework.ldap.core.support.LdapContextSource; SearchStrategy: all) did not find any beans (OnBeanCondition)

   LdapAutoConfiguration#ldapTemplate matched:
      - @ConditionalOnMissingBean (types: org.springframework.ldap.core.LdapOperations; SearchStrategy: all) did not find any beans (OnBeanCondition)

   LdapHealthContributorAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.ldap.core.LdapOperations' (OnClassCondition)
      - @ConditionalOnEnabledHealthIndicator management.health.ldap.enabled is true (OnEnabledHealthIndicatorCondition)
      - @ConditionalOnBean (types: org.springframework.ldap.core.LdapOperations; SearchStrategy: all) found bean 'ldapTemplate' (OnBeanCondition)

   LdapHealthContributorAutoConfiguration#ldapHealthContributor matched:
      - @ConditionalOnMissingBean (names: ldapHealthIndicator,ldapHealthContributor; SearchStrategy: all) did not find any beans (OnBeanCondition)

negative matches:
   EmbeddedLdapAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'com.unboundid.ldap.listener.InMemoryDirectoryServer' (OnClassCondition)

   LdapRepositoriesAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.springframework.data.ldap.repository.LdapRepository' (OnClassCondition)


o.s.b.actuate.ldap.LdapHealthIndicator   : LDAP health check failed
org.springframework.ldap.CommunicationException: localhost:389; nested exception is 
javax.naming.CommunicationException: localhost:389 
[Root exception is java.net.ConnectException: Connection refused: connect]

我的 AD 在远程服务器而不是本地主机上运行。 Spring 安全性工作正常。

那么为什么 LdapHealthIndicator 会尝试验证 localhost 上的 ldap 服务器呢?让 LdapHealthIndicator 从我的SecurityConfiguration 使用我的AuthenticationProvider 的设计方式是什么?

【问题讨论】:

您是否已经声明了您的spring.ldap 属性? Spring Security 不使用这些,但执行器会。比如你为spring.ldap.url设置了什么? 我试过 spring.ldap.url=ldaps://server.domain.tld 但执行器探针仍然是 localhost:389 我想知道你的依赖是否正确。例如。 spring-security-ldap 不依赖于声明了 LdapOperations 的 spring-ldap。你能分享一下你认为你在 pom 中包含的相关依赖项吗? 我添加了相关的依赖。有什么我应该在那里解决的吗? 【参考方案1】:

可能还有其他问题;但是,主要问题似乎是您的 pom 中缺少the spring-ldap-core dependency:

<dependency>
    <groupId>org.springframework.ldap</groupId>
    <artifactId>spring-ldap-core</artifactId>
</dependency>

包含它会将其放置在类路径中。结合正确的属性,Spring Boot 的 LDAP 自动配置将参与。

另外,the reference docs 声明该属性为spring.ldap.urls,所以我认为应该改为该属性。

【讨论】:

对不起。那没有奏效。我将依赖项和 spring.ldap.url 添加到我的 application.properties。但是执行器探针仍然是 localhost:389 没问题。接下来我要做的是使用--debug 程序参数并确认正在调用适当的Spring Boot Actuator 自动配置类。如果不是,调试输出通常足以告诉您原因。 我将 ldap 相关的调试输出添加到我的原始帖子中。但我仍然不明白为什么它确实添加了 ldap 执行器但无法验证服务器连接但使用 localhost。有什么想法吗? 感谢您提供额外的详细信息。我添加了一个指向参考文档的链接,这可能会指出您的配置存在的另一个问题。 “s”?哦真的吗?你很棒。使用 spring.ldap.urls 它终于可以工作了。非常感谢。

以上是关于如何让 Spring Boot Actuator LdapHealthIndicator 与 Spring Security 的 Ldap 一起运行?的主要内容,如果未能解决你的问题,请参考以下文章

spring-boot 速成 actuator

spring boot actuator 如何显示详细信息

如何启用Spring Boot Actuator的所有Endpoints

如何在 Spring Boot Actuator Prometheus 指标中包含时间戳

Spring Boot Actuator [监控与管理]

如何启用Spring Boot Actuator的所有Endpoints