🔐 Spring Boot Actuator 安全管理详解
Spring Boot Actuator 提供了强大的监控和管理能力,但其暴露的端点(如 /env、/beans、/shutdown)可能包含敏感信息或具备危险操作权限。若未妥善保护,极易引发安全风险,如配置泄露、服务被关闭、内存信息外泄等。
本文将系统性地讲解如何对 Actuator 进行安全管理,确保其在开发便利性与生产安全性之间取得平衡。
一、Actuator 的安全风险
| 端点 | 风险说明 |
|---|---|
/env | 泄露数据库密码、密钥、API Token 等敏感配置 |
/beans | 暴露内部 Bean 结构,可能被用于攻击分析 |
/shutdown | 可直接关闭应用(高危!) |
/heapdump | 生成堆转储文件,可能包含用户数据 |
/threaddump | 暴露线程堆栈,可能泄露业务逻辑 |
/mappings | 暴露所有接口路径,增加攻击面 |
🚨 结论:Actuator 端点必须进行访问控制,尤其是在生产环境中!
二、安全管理核心策略
✅ 1. 最小暴露原则(Principle of Least Exposure)
只暴露必要的端点,避免 management.endpoints.web.exposure.include=*
推荐生产环境配置:
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
❌ 禁止暴露:
env,beans,shutdown,heapdump,threaddump(除非运维需要)
✅ 2. 启用 Spring Security 进行认证与授权
(1)添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
(2)基础安全配置示例
@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// 允许所有人访问健康检查和 info
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health", "/actuator/info").permitAll()
// 其他 actuator 端点需要 ADMIN 角色
.requestMatchers("/actuator/**").hasRole("ADMIN")
// 其他请求放行
.anyRequest().permitAll()
)
// 启用 HTTP Basic 认证(简单有效)
.httpBasic(withDefaults())
// 关闭 CSRF(若使用 Basic 或 Token 可关闭)
.csrf().disable();
return http.build();
}
}
(3)配置管理员账号(application.yml)
spring:
security:
user:
name: ${ACTUATOR_USER:admin}
password: ${ACTUATOR_PASS:securePass123!}
roles: ADMIN
💡 建议使用环境变量注入密码,避免明文写在配置文件中。
✅ 3. 使用更安全的认证方式
方式一:基于 Token(如 JWT)
// 示例:使用 JWT 拦截 /actuator 请求
http
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/**").authenticated()
);
方式二:OAuth2 / OpenID Connect
适用于企业级 SSO 环境,结合 Keycloak、Auth0 等。
方式三:API Key 认证
@Order(1)
@Component
public class ApiKeyFilter implements Filter {
private static final String API_KEY = "your-secret-api-key";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
String key = req.getHeader("X-API-KEY");
if ("/actuator".equals(req.getServletPath()) ||
req.getServletPath().startsWith("/actuator/")) {
if (!API_KEY.equals(key)) {
((HttpServletResponse) response).setStatus(403);
return;
}
}
chain.doFilter(request, response);
}
}
✅ 4. 网络层隔离(推荐生产环境)
即使有认证,也建议通过网络层进一步限制访问:
| 方案 | 说明 |
|---|---|
| 反向代理(Nginx) | 只允许内网或运维网关访问 /actuator |
| 防火墙规则 | 限制只有特定 IP 可访问 8080 端口的 /actuator 路径 |
| 独立管理端口 | 将 Actuator 暴露在独立端口(如 8081),不对外网开放 |
配置独立管理端口:
management:
server:
port: 8081
address: 127.0.0.1 # 仅本地访问
✅ 效果:外部无法直接访问,需通过 SSH 隧道或运维网关访问。
✅ 5. 敏感信息脱敏
即使授权访问,也应避免明文显示敏感信息。
自定义 Environment 显示过滤
@Bean
public EnvironmentEndpointCustomizer environmentEndpointCustomizer() {
return endpoint -> endpoint.setEnvironmentFilter(
new EnvironmentFilter() {
private final Set<String> SENSITIVE_KEYS = Set.of(
"password", "secret", "key", "token", "database.url"
);
@Override
public PropertySources filter(PropertySources propertySources) {
return new PropertySources() {
@Override
public Iterator<PropertySource<?>> iterator() {
return new Iterator<PropertySource<?>>() {
private final Iterator<PropertySource<?>> delegate = propertySources.iterator();
@Override
public boolean hasNext() {
return delegate.hasNext();
}
@Override
public PropertySource<?> next() {
PropertySource<?> source = delegate.next();
return new PropertySource<Object>(source.getName()) {
@Override
public Object getProperty(String name) {
Object value = source.getProperty(name);
if (isSensitive(name)) {
return "******";
}
return value;
}
};
}
};
}
};
}
private boolean isSensitive(String name) {
return SENSITIVE_KEYS.stream().anyMatch(name::contains);
}
}
);
}
✅ 效果:访问
/actuator/env时,db.password=******
✅ 6. 禁用高危端点
明确禁用不需要的高危端点:
management:
endpoint:
shutdown:
enabled: false
heapdump:
enabled: false
threaddump:
enabled: false
env:
enabled: false
beans:
enabled: false
✅ 7. 审计日志(Audit Logging)
记录所有对 Actuator 的访问行为,便于追踪异常操作。
@Component
public class ActuatorAccessAuditListener {
private static final Logger log = LoggerFactory.getLogger(ActuatorAccessAuditListener.class);
@EventListener
public void handleAuditEvent(AuditEvent event) {
if (event.getType().startsWith("AUTH")) {
log.info("Audit: {} - {} - {}", event.getPrincipal(), event.getType(), event.getData());
}
}
}
结合 Spring Security 的 AuditEvent 机制,记录登录、访问尝试等。
三、生产环境推荐配置模板
# application-prod.yml
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
jmx:
exposure:
include: health,info
endpoint:
health:
show-details: when-authorized
shutdown:
enabled: false
env:
enabled: false
beans:
enabled: false
server:
port: 8081
address: 127.0.0.1
spring:
security:
user:
name: ${ADMIN_USER}
password: ${ADMIN_PASS}
roles: ACTUATOR_ADMIN
配合 Nginx 反向代理:
location /actuator/ {
allow 192.168.1.0/24; # 仅内网访问
deny all;
proxy_pass http://localhost:8081/;
}
四、常见安全误区
| 误区 | 正确做法 |
|---|---|
开发完忘记关闭 exposure.include=* | 使用 Profile 区分 dev/prod |
密码写死在 application.yml | 使用环境变量或配置中心 |
| 仅靠防火墙,无认证 | 防火墙 + 认证双保险 |
| 所有运维人员共用账号 | 使用 OAuth2 或 JWT 实现用户级审计 |
忽略 /actuator 路径扫描风险 | 使用 WAF 或隐藏路径(如加前缀) |
五、总结:Actuator 安全 checklist
✅ 必须做:
- 限制暴露端点(只开 health/info/metrics)
- 启用 Spring Security 认证
- 禁用
shutdown、env等高危端点 - 使用独立管理端口或网络隔离
✅ 推荐做:
- 敏感信息脱敏
- 记录审计日志
- 使用 API Key 或 JWT
- 配合 Prometheus + Grafana 可视化,减少直接访问
🔐 安全不是功能,而是责任。合理配置 Actuator 安全策略,才能在享受其强大功能的同时,保障系统稳定与数据安全。

7347

被折叠的 条评论
为什么被折叠?



