Spring Boot Actuator 中的端点管理

1、概览

本文将带你了解如何通过 properties 文件控制 Spring Boot Actuator 端点的状态,以及如何保证端点的安全。

2、设置

为了使用 Actuator,需要在 Maven 配置中包含 spring-boot-starter-actuator

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <version>3.1.2</version>
</dependency>

此外,从 Spring Boot 2.0 开始,如果想通过 HTTP 暴露端点,就需要包含 Web Starter

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.1.2</version>
</dependency>

3、启用和暴露端点

默认情况下,除 /shutdown 之外的所有端点都已启用,只有 /health/info 被暴露。即使为应用配置了不同的 Root Context,也能在 /actuator 中找到所有端点。

这意味着,一旦在 Maven 配置中添加了相应的 Stater,就可以访问 http://localhost:8080/actuator/healthhttp://localhost:8080/actuator/info 上的 /health/info 端点。

访问 http://localhost:8080/actuator,查看可用端点列表,因为 Actuator 端点已启用 HATEOS。所以,应该能看到 /health/info

{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},
"health":{"href":"http://localhost:8080/actuator/health","templated":false},
"info":{"href":"http://localhost:8080/actuator/info","templated":false}}}

3.1、暴露所有端点

现在,修改 application.properties 文件来暴露除 /shutdown 以外的所有端点:

management.endpoints.web.exposure.include=*

重新启动服务器并再次访问 /actuator 端点,就能看到除 /shutdown 以外的其他可用端点:

{"_links":{"self":{"href":"http://localhost:8080/actuator","templated":false},
"beans":{"href":"http://localhost:8080/actuator/beans","templated":false},
"caches":{"href":"http://localhost:8080/actuator/caches","templated":false},
"health":{"href":"http://localhost:8080/actuator/health","templated":false},
"info":{"href":"http://localhost:8080/actuator/info","templated":false},
"conditions":{"href":"http://localhost:8080/actuator/conditions","templated":false},
"configprops":{"href":"http://localhost:8080/actuator/configprops","templated":false},
"env":{"href":"http://localhost:8080/actuator/env","templated":false},
"loggers":{"href":"http://localhost:8080/actuator/loggers","templated":false},
"heapdump":{"href":"http://localhost:8080/actuator/heapdump","templated":false},
"threaddump":{"href":"http://localhost:8080/actuator/threaddump","templated":false},
"metrics":{"href":"http://localhost:8080/actuator/metrics","templated":false},
"scheduledtasks":{"href":"http://localhost:8080/actuator/scheduledtasks","templated":false},
"mappings":{"href":"http://localhost:8080/actuator/mappings","templated":false}}}

3.2、暴露特定端点

有些端点可能会暴露敏感数据,因此要谨慎。

可以通过 management.endpoints.web.exposure.include 属性来指定要暴露的端点列表,多个属性之间使用逗号分隔。

如下,只暴露 /beans/loggers 这两个端点:

management.endpoints.web.exposure.include=beans, loggers

除了用属性包含某些端点外,还可以排除端点。

如下,暴露除 /threaddump 之外的所有端点:

management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=threaddump

includeexclude 属性都包含一个端点列表。exclude 属性优先于 include 属性。

3.3、启用特定端点

接下来看看如何只启用指定的端点。

首先,关闭启用所有端点的默认设置:

management.endpoints.enabled-by-default=false

接下来,只启用并暴露 /health 端点:

management.endpoint.health.enabled=true
management.endpoints.web.exposure.include=health

通过如上这种配置,只有 /health 端点可被访问。

3.4、启用 Shutdown 端点

由于其敏感性,/shutdown 端点默认为禁用。

application.properties 文件中添加一行,启用它:

management.endpoint.shutdown.enabled=true

现在,当查询 /actuator 端点时,就会看到它被列出。/shutdown 端点只接受 POST 请求。

请求 /shutdown 端点,优雅地关闭应用:

curl -X POST http://localhost:8080/actuator/shutdown

4、保护端点

在实际应用中,需要确保 Actuator 端点的安全。

首先,添加 Security Starter Maven 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.5.1</version>
</dependency>

对于最基本的安全设置来说,这样就够了。只需添加 security starter,就能自动将 Basic Authentication 应用到除 /info/health 之外的所有暴露端点。

现在,自定义安全设置,将 /actuator 端点限制为只有 ADMIN 角色可访问。

从排除默认安全配置开始:

@SpringBootApplication(exclude = { 
    SecurityAutoConfiguration.class, 
    ManagementWebSecurityAutoConfiguration.class 
})

注意 ManagementWebSecurityAutoConfiguration.class,它可以让我们将自己的安全配置应用到 /actuator

在配置类中,配置几个用户和角色:

@Bean
public InMemoryUserDetailsManager userDetailsService() {
    UserDetails user =  User.withDefaultPasswordEncoder()
        .username("user")
        .password("password")
        .roles("USER")
        .build();
    UserDetails admin =  User.withDefaultPasswordEncoder()
        .username("admin")
        .password("password")
        .roles("USER", "ADMIN") // USER、ADMIN 角色
        .build();
    return new InMemoryUserDetailsManager(user, admin);
}

SpringBoot 为 Actuator 端点提供了一个方便的请求匹配器(Request Matcher)。

用它来匹配 /actuator,使其只能用于 ADMIN 角色:

http.authorizeHttpRequests(authz -> {
        authz.requestMatchers(mvc.pattern("/actuator/**"))
            .hasRole("ADMIN")
            .anyRequest()
            .authenticated();
    });

5、总结

本文介绍了如何在 Spring Boot 中启用、禁用、暴露 Actuator 端点,以及如何使用 Spring Security 来保证 Actuator 端点的安全。


Ref:https://www.baeldung.com/spring-boot-actuator-enable-endpoints