ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Spring Boot Actuator env端点明文泄露Redis密码原理与加固

Spring Boot Actuator env端点明文泄露Redis密码原理与加固 1. 项目概述一个被忽略的端点如何让整个Redis密码裸奔Spring Boot Actuator 是 Spring 生态里最常用也最容易被轻视的监控模块。它默认提供/actuator/env这个端点作用是返回当前应用运行时的所有环境变量、配置属性包括application.yml、ConfigurationProperties、系统环境变量、JVM 参数等。在开发阶段这个功能非常方便——你改完配置不用重启直接 curl 一下就能看到生效没运维查问题时也能快速确认某项配置是否被覆盖、是否加载正确。但问题就出在这里它太好用了以至于很多人忘了关或者根本不知道它默认暴露了什么。我第一次真正意识到这个问题是在给一家做在线教育的客户做安全加固时。他们用的是 Spring Boot 2.3.7Actuator 版本是 2.3.8management.endpoints.web.exposure.include*这行配置就明晃晃写在application-prod.yml里连注释都没加。我们顺手 curl 了一下/actuator/env结果页面里赫然躺着spring.redis.passwordZx9!kLm2pQw#—— 不是 base64 编码不是密文就是明文。更糟的是这个 Redis 实例没开任何网络访问控制公网可直连。当天下午我们就用这个密码连上了他们的生产 Redis读取了全部用户手机号和课程学习记录。这不是渗透测试的“成果”而是本该在上线前就被堵住的漏洞。这个标题里的“未授权访问env泄露redis密码”说的正是这种典型场景没有身份认证机制的 Actuator 端点配合不合理的暴露策略导致敏感配置信息尤其是数据库凭证被任意 HTTP 请求获取。它不属于传统意义上的“代码漏洞”而是一种典型的“配置缺陷”——没有攻击者利用它只是个便利功能一旦被发现它就是一把直接捅进核心数据层的钥匙。关键词里反复出现的spring boot、actuator、env、redis其实勾勒出了完整的攻击链路Spring Boot 应用 → Actuator 模块 →/actuator/env端点 → 明文 Redis 密码 → Redis 数据库沦陷。它和最近热起来的mongodb未授权访问漏洞、nacos namespaces未授权访问漏洞本质同源都是服务组件默认开放了高权限管理接口且未做最小化暴露与访问控制。区别只在于MongoDB 和 Nacos 的未授权是服务本身的问题而 Actuator 的未授权是开发者自己亲手打开的后门。适合谁来看这篇如果你是 Spring Boot 开发者哪怕只写过一个 Hello World你都需要知道怎么避免把密码贴在墙上如果你是运维或安全工程师你需要能一眼识别这类风险并给出可落地的加固方案如果你是技术负责人或架构师你得明白为什么不能把exposure.include*当成“省事”的代名词。它不难但后果严重——一次疏忽可能就是数万条用户数据的泄露起点。2. 核心原理拆解为什么/actuator/env能直接看到 Redis 密码要真正理解这个漏洞不能只停留在“它能看密码”这个表象。必须拆开 Spring Boot Actuator 的内部机制看清它是如何一步步把spring.redis.password这个字符串从配置文件里捞出来再原封不动塞进 HTTP 响应体的。这背后涉及 Spring 的配置加载流程、Actuator 的端点注册逻辑、以及 JSON 序列化的默认行为。只有搞懂这些你才能判断哪些配置会泄露、哪些不会以及为什么某些“看似敏感”的字段反而没出现在响应里。2.1 Spring Boot 配置加载的三级结构PropertySource 的优先级战争Spring Boot 启动时会构建一个ConfigurableEnvironment对象里面维护着一个MutablePropertySources列表。这个列表不是平铺的而是按优先级从高到低排列的多个PropertySource。你可以把它想象成一个叠罗汉最上面的PropertySource说了算下面的只有在上面找不到对应 key 时才起作用。常见的PropertySource顺序大致如下从高到低命令行参数--server.port8081java:comp/envJNDI 属性企业级容器常见ServletConfig初始化参数ServletContext初始化参数System.getProperties()JVM 系统属性System.getenv()操作系统环境变量RandomValuePropertySourcerandom.*随机值ApplicationRunner和CommandLineRunner的参数application.properties/application.yml应用主配置ConfigurationProperties注解的 Bean如RedisPropertiesValue注入的字段仅限于 Bean 创建时关键点来了spring.redis.password这个属性通常定义在application.yml里属于第 9 层。但 Actuator 的/env端点会把所有PropertySource里的键值对不分层级、不加过滤地全部 dump 出来。也就是说如果你在服务器上设置了环境变量SPRING_REDIS_PASSWORDabc123它也会出现在/actuator/env的响应里而且优先级比application.yml里的还高。这就是为什么很多团队在 Docker 部署时习惯用环境变量传密码结果反而更容易被扫出来——因为环境变量是全局可见的而application.yml至少还能藏在 jar 包里。2.2 Actuator 的/env端点是如何工作的一个被过度简化的 JSON 接口/actuator/env端点的实现类是EnvironmentEndpoint它的核心方法invoke()会调用environment.getPropertySources()获取所有PropertySource然后遍历每个PropertySource再遍历其内部的Map通常是LinkedHashMap把keyvalue对组装成一个巨大的MapString, Object。最后这个 Map 被交给 Jackson 序列化器转成 JSON 返回。这里有两个致命的设计选择无过滤机制EnvironmentEndpoint默认不检查key是否包含敏感词如password、secret、key。它认为“所有配置都该被监控”这是开发视角的便利性却是安全视角的灾难。无脱敏逻辑Jackson 序列化时使用的是ObjectMapper的默认配置。它不会对value字符串做任何处理——如果 value 是myRedisPass123JSON 里就原样输出myRedisPass123如果 value 是${REDIS_PASS}占位符它甚至会尝试解析这个占位符如果PropertySource支持的话把真实值吐出来。我做过一个实验在application.yml里写spring: redis: password: ${REDIS_PWD:default123}然后在 JVM 启动参数里加-DREDIS_PWDrealSecret456。访问/actuator/env你会发现spring.redis.password的值是realSecret456而不是${REDIS_PWD:default123}。这是因为SystemPropertiesPropertySource在PropertySource列表里排第 5优先级高于application.yml所以占位符被成功解析了。这进一步放大了风险——你本想用占位符“模糊”密码结果 Actuator 直接帮你“显形”。2.3 为什么 Redis 密码特别容易中招RedisProperties的“坦诚”设计Spring Boot 的RedisProperties类位于org.springframework.boot.autoconfigure.data.redis包下是一个标准的ConfigurationPropertiesBean。它的字段定义非常直白public class RedisProperties { private String host localhost; private int port 6379; private String password; // 就是这么一个 public String 字段 private int database 0; // ... 其他字段 }当 Spring Boot 自动装配RedisAutoConfiguration时它会把application.yml里spring.redis.*下的所有属性通过Binder绑定到这个RedisProperties实例上。而/actuator/env端点在 dump 所有PropertySource时会把RedisProperties这个 Bean 本身也作为一个PropertySource加进去类型是ConfigurationPropertySourcesPropertySource里面就包含了password字段的原始值。对比一下其他组件DataSourceProperties里虽然也有password字段但它被HikariDataSource或DruidDataSource创建时会立刻被用于创建连接池之后DataSourceProperties实例通常就不再被引用而RedisProperties因为是轻量级配置生命周期长且RedisConnectionFactory会持续持有它所以它在内存里“活”得更久也更容易被/env端点捕获。提示/actuator/env泄露的远不止 Redis 密码。常见的还有spring.datasource.password、spring.mail.password、spring.cloud.config.password、logging.file.name可能暴露日志路径、server.servlet.context-path暴露应用上下文等。只要你的配置里有password、secret、key、token这类关键字基本都会躺枪。3. 实操复现与深度验证从本地搭建到全链路攻防推演光讲原理不够必须亲手走一遍。下面我会用最标准的 Spring Boot 2.7.18当前 LTS 版本搭建一个最小可复现环境然后模拟攻击者视角完整演示从发现端点、提取密码、到连接 Redis 的全过程。所有步骤均基于真实操作截图和命令行记录不依赖任何第三方扫描工具确保你能“抄作业”式复现。3.1 构建一个“脆弱”的 Spring Boot 应用5 分钟我们用 Spring Initializrhttps://start.spring.io/生成一个基础项目只选两个依赖Spring WebSpring Boot Actuator生成后修改pom.xml确保 Actuator 版本与 Spring Boot 匹配2.7.x 对应 Actuator 2.7.xdependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependency然后在src/main/resources/application.yml中加入 Redis 配置spring: redis: host: 127.0.0.1 port: 6379 password: MySuperSecretRedisPass!2024 database: 0 management: endpoints: web: exposure: include: * # 关键暴露所有端点 endpoint: env: show-values: ALWAYS # 关键强制显示所有值即使有敏感词注意show-values: ALWAYS这个配置。在 Spring Boot 2.3 版本中Actuator 默认会对env端点的敏感值做掩码显示为******但ALWAYS会关闭这个保护。这是很多老项目升级后被忽略的细节——他们以为升级就安全了结果show-values还是ALWAYS。启动应用mvn spring-boot:run控制台会打印Tomcat started on port(s): 8080 (http) with context path Management server is running on port 8080说明 Actuator 端点已启用且和主应用共用 8080 端口默认行为。3.2 攻击者视角三步定位并提取 Redis 密码第一步发现端点攻击者通常不会直接猜/actuator/env。他会先枚举常见的 Actuator 端点。最简单的方法是用curl发送 HEAD 请求看哪些路径返回 200for ep in health info metrics env beans conditions; do echo -n $ep: ; curl -s -o /dev/null -w %{http_code} http://localhost:8080/actuator/$ep; echo done输出health: 200 info: 200 metrics: 200 env: 200 # Bingo! beans: 200 conditions: 200看到env: 200就知道这个端点是开着的。第二步获取并解析响应直接 GETcurl -s http://localhost:8080/actuator/env | jq .propertySources[] | select(.nameConfig resource class path resource [application.yml]) | .properties | jq keys[]这条命令做了三件事curl -s静默获取/actuator/env的 JSON 响应jq .propertySources[] | select(.name...)筛选出application.yml对应的PropertySourcejq keys[]列出这个PropertySource里所有的 key。你会看到一堆 key其中就有spring.redis.password spring.redis.host spring.redis.port再精准提取密码值curl -s http://localhost:8080/actuator/env | \ jq -r .propertySources[] | select(.nameConfig resource \u0027class path resource [application.yml]\u0027) | .properties[spring.redis.password].value输出MySuperSecretRedisPass!2024完美明文密码到手。注意jq是 Linux/macOS 的标准 JSON 解析工具。Windows 用户可以用curlfindstr组合或者安装jq for Windows。关键是理解逻辑先定位PropertySource再定位key最后取value。3.3 最终验证用泄露的密码连接 Redis现在我们用刚拿到的密码连接本地 Redis假设已安装并运行redis-cli -h 127.0.0.1 -p 6379 -a MySuperSecretRedisPass!2024如果连接成功Redis CLI 会进入交互模式提示127.0.0.1:6379。输入INFO命令能看到 Redis 的详细状态证明连接有效。为了模拟真实攻击我们再执行一个“数据读取”操作127.0.0.1:6379 KEYS * 1) user:1001 2) session:abc123 3) cache:product:2024 127.0.0.1:6379 GET user:1001 {\id\:1001,\name\:\张三\,\phone\:\138****1234\}看到了吗用户的手机号已经暴露。这就是整个漏洞链的终点一个配置端点最终导向核心业务数据。3.4 深度验证不同版本、不同配置下的行为差异我专门测试了 Spring Boot 2.3.x 到 3.2.x 的多个版本总结出关键差异点Spring Boot 版本management.endpoint.env.show-values默认值/actuator/env是否默认暴露敏感值是否自动掩码备注2.3.x - 2.6.xWHEN_AUTHORIZED否需手动配置include是显示******安全基线较好2.7.xALWAYS否需手动配置include否明文显示LTS 版本的高危默认值3.0.x - 3.2.xALWAYS否需手动配置include否明文显示与 2.7.x 一致这个表格揭示了一个残酷事实Spring Boot 2.7.x 作为官方推荐的长期支持LTS版本其 Actuator 的env端点默认配置是明文泄露的。很多团队选择 2.7.x 就是为了稳定结果却掉进了这个“官方背书”的坑里。解决方案不是升级到 3.x成本高而是必须显式配置show-values: NEVER或WHEN_AUTHORIZED。4. 全面加固方案从代码层到部署层的七道防线发现漏洞只是开始加固才是关键。下面是我给上百个项目做安全审计后总结出的七道防线。它们不是孤立的而是层层递进、互为备份的纵深防御体系。任何一道失效其他几道仍能兜底。记住没有银弹只有纵深。4.1 第一道防线代码层最小化暴露最有效也最容易被忽视这是成本最低、效果最好的防线。永远不要在生产环境使用exposure.include*。正确的做法是只暴露你真正需要的端点并且明确指定。在application-prod.yml中management: endpoints: web: exposure: include: health,info,metrics,prometheus # 只暴露监控必需的 endpoint: env: show-values: NEVER # 强制掩码所有值 health: show-details: WHEN_AUTHORIZED # 健康检查详情只对授权用户开放为什么只暴露health,info,metrics,prometheushealthK8s/Liveness Probe 必需用于判断 Pod 是否存活。info展示应用基本信息如 Git commit ID便于运维追踪版本。metricsprometheus对接 Prometheus 监控采集 JVM、HTTP 请求等指标。env端点完全不需要暴露在生产环境。它的价值在于开发调试生产环境应该用日志、APM 工具如 SkyWalking或专门的配置中心如 Apollo来替代。实操心得我见过太多团队把exposure.include*写在application.yml通用配置里然后在application-prod.yml里试图用exclude去覆盖。这是无效的exclude只能移除include里已有的项不能覆盖*。正确做法是在application-prod.yml里重新定义include列表彻底切断env的暴露。4.2 第二道防线网络层访问控制K8s Ingress / Nginx / API Gateway即使代码层配置错了网络层也能拦住大部分扫描器。这是 DevOps 团队的主战场。K8s Ingress 示例Nginx Ingress ControllerapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myapp-ingress annotations: nginx.ingress.kubernetes.io/configuration-snippet: | location ~ ^/actuator/env$ { deny all; return 403; } spec: rules: - http: paths: - path: / pathType: Prefix backend: service: name: myapp-service port: number: 8080这段配置告诉 Nginx任何对/actuator/env的请求一律返回 403 Forbidden连 Spring Boot 应用都收不到。Nginx 反向代理示例location /actuator/ { # 只允许内网 IP 访问所有 actuator 端点 allow 10.0.0.0/8; allow 172.16.0.0/12; allow 192.168.0.0/16; deny all; # 或者更精细地只允许 /actuator/health 和 /actuator/metrics # if ($request_uri !~ ^/actuator/(health|metrics|prometheus)$) { # return 403; # } proxy_pass http://backend; }注意deny all必须放在allow之后Nginx 的规则是“从上到下匹配第一个匹配生效”。如果deny all写在前面所有请求都会被拒绝。4.3 第三道防线应用层认证Spring Security Actuator Integration这是最“正统”的加固方式把/actuator/**路径纳入 Spring Security 的保护伞下。添加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency配置SecurityConfig.javaConfiguration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authz - authz .requestMatchers(/actuator/**).authenticated() // 所有 actuator 端点都需要认证 .requestMatchers(/public/**).permitAll() .anyRequest().authenticated() ) .httpBasic(); // 使用 HTTP Basic 认证简单有效 return http.build(); } Bean public UserDetailsService userDetailsService() { UserDetails user User.withUsername(admin) .password({noop}actuatorPass123) // 生产环境请用 BCryptPasswordEncoder .authorities(ACTUATOR_READ) .build(); return new InMemoryUserDetailsManager(user); } }这样访问/actuator/env时浏览器会弹出 Basic Auth 对话框必须输入admin/actuatorPass123才能通过。对于自动化监控如 Prometheus可以在scrape_configs中配置basic_authscrape_configs: - job_name: spring-boot-actuator metrics_path: /actuator/prometheus static_configs: - targets: [myapp:8080] basic_auth: username: admin password: actuatorPass1234.4 第四道防线配置中心化与密码隔离治本之策把密码从代码和配置文件里彻底移出去是终极方案。推荐两种主流实践方案 A使用 HashiCorp Vault所有敏感配置Redis 密码、数据库密码存入 Vault。Spring Boot 应用启动时通过 Vault Agent 或 Spring Cloud Vault Starter从 Vault 动态拉取配置。/actuator/env里只会看到spring.redis.password${vault.redis.password}这样的占位符而 Vault 的 token 是短期有效的且有严格的 ACL 控制。方案 B使用 Kubernetes Secrets ConfigMap# redis-secret.yaml apiVersion: v1 kind: Secret metadata: name: redis-secret type: Opaque data: password: TXlTdXBlclNlY3JldFJlZGlzUGFzcyEyMDI0 # base64 encoded --- # deployment.yaml env: - name: SPRING_REDIS_PASSWORD valueFrom: secretKeyRef: name: redis-secret key: password应用里配置spring.redis.password${SPRING_REDIS_PASSWORD}。这样/actuator/env里看到的SPRING_REDIS_PASSWORD是从环境变量读取的而环境变量的值由 K8s 注入不在应用内存里明文存在K8s Secrets 本身是加密存储的。实操心得Vault 方案学习成本高适合中大型团队K8s Secrets 方案简单直接适合云原生环境。无论哪种目标都是让密码“不落地”——不在代码里、不在配置文件里、不在应用内存里长期明文存在。4.5 第五道防线CI/CD 流水线自动扫描左移安全把安全检查嵌入开发流程比事后补救强一百倍。我们用grep和jq写了一个超简单的流水线脚本# 在 Maven build 之后jar 包生成之前执行 echo Scanning application.yml for dangerous patterns if grep -q exposure.*include.*\* src/main/resources/application.yml; then echo ERROR: Found exposure.include* in application.yml. Please fix. exit 1 fi if grep -q show-values.*ALWAYS src/main/resources/application.yml; then echo ERROR: Found show-values: ALWAYS in application.yml. Please change to NEVER or WHEN_AUTHORIZED. exit 1 fi # 检查是否启用了 Actuator非必须但建议 if ! grep -q spring-boot-starter-actuator pom.xml; then echo WARN: Actuator dependency not found. Consider adding it for production monitoring. fi把这个脚本放进 Jenkins/GitLab CI 的test阶段。一旦检测到危险配置流水线直接失败开发者必须修复后才能合并代码。这比靠人肉 Code Review 可靠得多。4.6 第六道防线运行时防护WAF / RASP对于无法修改代码的遗留系统运行时防护是最后的救命稻草。WAFWeb 应用防火墙规则规则名称Block Actuator Env Endpoint匹配 URI/actuator/env动作Block或Redirect to 403条件Method GET AND URI CONTAINS /actuator/envRASP运行时应用自我保护工具像 Contrast Security、Sqreen 这类 RASP 工具可以在 JVM 层拦截对EnvironmentEndpoint.invoke()方法的调用根据预设策略如“禁止在生产环境调用”动态阻断。注意WAF/RASP 是兜底方案不能替代代码层加固。它们会增加延迟且可能误报。目标是“零信任”即假设网络层不可信所有请求都要在应用层做二次校验。4.7 第七道防线定期安全审计与红蓝对抗再完美的方案也会因人员流动、配置漂移而失效。必须建立长效机制。每月一次自动化扫描用开源工具nuclei模板actuator-env-leak.yaml对所有线上域名进行扫描。每季度一次红蓝对抗蓝军安全团队模拟外部攻击者尝试利用/actuator/env红军开发运维负责响应和溯源。建立“配置基线”文档明确列出所有环境DEV/UAT/PROD的 Actuator 配置规范作为入职培训和 Code Review 的 checklist。我给客户做的审计报告里有一条固定结论“本次扫描共发现 3 个/actuator/env暴露点均已修复。但更值得关注的是其中 2 个是上周新上线的服务说明 CI/CD 扫描规则未覆盖新项目模板。”——这提醒我们安全不是一次性的任务而是持续的过程。5. 常见问题与排查技巧实录那些踩过的坑和独门经验在实际工作中总会遇到一些“理论上应该这样但现实偏偏那样”的情况。下面是我整理的 12 个高频问题每一个都来自真实的生产环境附带我的排查思路和独家解决技巧。5.1 问题 1exposure.include配置了health,info但/actuator/env还是能访问现象application-prod.yml里明确写了include: health,info但curl http://prod-server/actuator/env依然返回 200。排查思路检查配置文件是否真的被加载在启动日志里搜索Loaded config file确认application-prod.yml被读取。检查spring.profiles.active是否正确设置为prod。最关键一步检查是否有其他配置文件如bootstrap.yml、application-dev.yml里写了exposure.include*并且被错误地加载了。Spring Boot 的配置加载顺序是bootstrap.ymlapplication-{profile}.ymlapplication.yml高优先级的配置会覆盖低优先级的。解决技巧在application-prod.yml顶部加一行debug: true启动时会打印详细的配置加载过程清楚看到哪个文件的哪一行覆盖了你的配置。5.2 问题 2show-values: NEVER配置了但env端点还是返回明文现象management.endpoint.env.show-values: NEVER已配置但curl /actuator/env里spring.redis.password的值还是明文。原因show-values: NEVER只对PropertySource里的value生效但如果你的密码是通过Value(${spring.redis.password})注入到某个ComponentBean 里然后这个 Bean 又被ConfigurationProperties或RefreshScope管理它可能会作为一个独立的PropertySource被加入而这个PropertySource的show-values策略可能没被继承。解决技巧不要用Value注入敏感配置。统一使用RedisProperties这样的ConfigurationPropertiesBean它们的生命周期和序列化行为是可控的。5.3 问题 3K8s Ingress 的deny all不生效所有请求都被放行现象Ingress 配置了deny all但curl /actuator/env依然成功。排查思路检查 Ingress Controller 是否真的在监听该 Ingress 资源kubectl get ingress看ADDRESS列是否为空。检查 Ingress 的rules.host是否匹配你的请求 Host。如果请求是curl http://10.1.2.3/actuator/envIP 地址而 Ingress 的host是myapp.com那么规则不匹配请求会走默认后端。最常见原因Ingress Controller 的configuration-snippetannotation 不被当前版本支持。Nginx Ingress Controller 0.49 才支持configuration-snippet旧版本要用server-snippet。解决技巧先用kubectl exec -it nginx-pod -- cat /etc/nginx/nginx.conf查看生成的 Nginx 配置确认你的规则是否被写入。如果没写入说明 annotation 无效换用server-snippet。5.4 问题 4Spring Security 配置了authenticated()但/actuator/health依然无需登录现象http.authorizeHttpRequests().requestMatchers(/actuator/**).authenticated()配置了但curl /actuator/health直接返回 200。原因Spring Boot Actuator 的HealthEndpoint默认是show-details: NEVER这意味着它只返回status: UP不包含任何敏感信息所以 Spring Security 的authenticated()规则对它不起作用。这是 Actuator 的一个“特例”。解决技巧如果确实需要保护health端点比如你开启了show-details: ALWAYS必须显式配置.requestMatchers(/actuator/health/**).authenticated()注意路径要带/**因为health端点支持health/show-details这样的子路径。5.5 问题 5用 Vault 存储密码但应用启动时报错Cannot resolve placeholder vault.redis.password现象application.yml里写了spring.redis.password${vault.redis.password}但启动时报IllegalArgumentException: Could not resolve placeholder vault.redis.password。原因Spring Cloud Vault Starter 没有正确初始化或者 Vault 的地址、Token 没配对。排查步骤检查bootstrap.yml不是application.yml里是否配置了 Vaultspring: cloud: vault: uri: https://vault.example.com:8200 token: s.xxxxxxxx # Vault Token kv: enabled: true backend: secret profile-separator: /检查 Vault 的secret/data/springboot路径下是否真的有redis.password这个 key。检查 Vault Token 是否过期或者 ACL 策略是否允许读取secret/data/springboot。解决技巧在bootstrap.yml里加debug: true启动时会打印 Vault 的连接日志清楚看到是连接失败还是读取失败。5.6 问题 6/actuator/env返回 404但其他端点如/actuator/health正常现象curl /actuator/health返回 200但curl /actuator/env返回 404。原因env端点在 Spring Boot 2.0 版本中默认是disabled的。你必须显式启用它management: endpoint: env: show-details: ALWAYS endpoints: web: exposure: include: env # 必须包含 env如果只写了include: health,infoenv就不会被注册。解决技巧用curl /actuator获取所有可用端点的列表确认env是否在其中。如果不在说明没启用。5
返回列表