Spring Boot Actuator 未授权访问防护实战:生产环境端点安全配置

适用场景

Spring Boot Actuator 未授权访问是生产环境高发的安全风险:开发者开启 actuator 后忘记加鉴权,攻击者访问 /actuator/env 读取数据库密码、/actuator/heapdump 下载堆内存文件提取密钥、甚至调用 /actuator/shutdown 关闭应用。本文适用于:Spring Boot 2.x/3.x 应用上线前安全检查、已发现 actuator 暴露需紧急收敛的场景,以及需要满足等保测评对敏感信息泄露防护要求的团队。

前置条件

  • Spring Boot 2.x 或 3.x 项目,已引入 spring-boot-starter-actuator
  • 项目使用 Maven 或 Gradle 构建
  • 具备源码修改权限,可重新打包部署
  • 若使用 Spring Security 方案,需已引入 spring-boot-starter-security

原理说明

Actuator 是 Spring Boot 提供的生产监控组件,默认暴露 health 端点,但开发者常通过 management.endpoints.web.exposure.include=* 开放全部端点。其中敏感端点包括:

  • env / configprops:泄露数据源密码、密钥等配置
  • heapdump:导出 JVM 堆快照,可离线提取凭据(最高危
  • shutdown:直接关闭应用,构成 DoS
  • jolokia / loggers:可执行 JMX 操作或修改日志级别辅助攻击

防御原则是最小暴露 + 强制鉴权:生产环境只暴露必要的 health/info 端点,其余全部关闭;必须暴露的敏感端点一律通过 Spring Security 限制访问来源(IP 白名单或账号鉴权)。

操作步骤

步骤一:裁剪暴露端点(最优先)

application.yml 中显式指定仅暴露健康检查端点,禁用 heapdump/shutdown/env 等敏感端点关键配置):

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info
  endpoint:
    health:
      show-details: never        # 不展示数据库等明细
    shutdown:
      enabled: false             # 显式禁用 shutdown

同时建议修改默认路径,降低被扫描命中的概率:

management:
  endpoints:
    web:
      base-path: /internal-monitor  # 默认 /actuator,改为随机路径

步骤二:引入 Spring Security 强制鉴权

若业务必须保留部分敏感端点,用 Security 拦截。在 pom.xml 添加依赖:

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

配置类(Spring Boot 3.x 写法):

@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
          .securityMatcher("/internal-monitor/**")
          .authorizeHttpRequests(auth -> auth.anyRequest().hasRole("MONITOR"))
          .httpBasic(Customizer.withDefaults());
        return http.build();
    }
}

在 application.yml 中定义监控账号(生产环境建议配合环境变量注入,勿硬编码):

spring:
  security:
    user:
      name: monitor
      password: ${MONITOR_PASSWORD}   # 通过环境变量注入强密码
      roles: MONITOR

步骤三:端口隔离(进阶方案)

将 actuator 单独绑定到内网管理端口,与业务端口物理隔离:

management:
  server:
    port: 9081                    # 独立端口,不对外暴露
    address: 127.0.0.1            # 仅本机可访问,配合 Nginx 内网反代

步骤四:线上自查命令

# 检查敏感端点是否可匿名访问(应返回 401 或 404)
curl -i http://your-app:8080/actuator/env | head -5
curl -i http://your-app:8080/actuator/heapdump -o /dev/null -w "%{http_code}\n"
# 若已加固,应分别返回 401(鉴权)或 404(未暴露)

配置验证

# 1) 重新打包并启动
mvn clean package -DskipTests && java -jar target/app.jar
# 2) 未登录访问敏感端点 -> 401
curl -i http://localhost:8080/actuator/env | grep -E "HTTP/|401"
# 3) 带监控账号访问 -> 200 且只返回健康数据
curl -u monitor:密码 http://localhost:8080/actuator/health
# 4) 确认 heapdump 端点已不存在 -> 404
curl -i http://localhost:8080/actuator/heapdump | head -3
# 5) 若配置了独立端口,业务端口 8080 的 /actuator 应直接 404

常见问题

FAQ 1:配置了 include: health,info 但 /actuator/env 仍能访问?

检查是否存在多个配置文件覆盖(如 application-dev.yml 覆盖了 include 配置)或使用了旧的 management.endpoints.web.exposure.include=* 语法残留。建议用 spring.config.import 统一管理,并在启动日志中确认实际生效的 include 值。

FAQ 2:Spring Security 配置后业务接口也要求登录了?

说明 securityMatcher 未生效,Security 默认拦截所有请求。确认使用 securityMatcher(“/internal-monitor/**”) 限定匹配范围(Spring Boot 3.x),Spring Boot 2.x 使用 antMatchers 写法,两种版本 API 不通用。

FAQ 3:health 端点需要保留给云监控探活,怎么办?

保留 health 暴露即可,但务必设置 show-details: never(Spring Boot 2.x 为 never,3.x 为 never/always),避免探活接口泄露数据库状态与版本信息,并用 IP 白名单限制监控探活来源。

总结

Spring Boot Actuator 未授权访问的防御核心是最小暴露 + 强制鉴权 + 端口隔离三层叠加:生产环境仅暴露 health/info,敏感端点全部关闭;确需保留的端点通过 Spring Security 做账号/IP 双重限制;进阶场景将 actuator 隔离到内网独立端口。建议将此配置纳入上线安全检查清单,部署后立即用 curl 自查一遍敏感端点。