适用场景
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 自查一遍敏感端点。