按框架
Spring Boot 安全加固 —— 生产环境加固实务参考
一份 Spring Boot 生产环境加固实务参考:优先级清单,外加依赖 CVE(Log4Shell)、生产配置与密钥、Spring Security 授权、Actuator 暴露、反序列化与 SSRF。仅讲防御,不含攻击步骤。
面向:任何运行 Java / Spring Boot 应用的人。这里不讲攻击步骤 —— 这是一份用于加固的实务参考:按优先级排序的清单、分领域的对策,以及自查。想看跨框架的全貌,请参阅 按框架分类的安全入口。
按优先级排序的加固清单
自上而下落实这张表。P0 是前提,P1 是最高频的事故源,P2 是持续的运维卫生。
P0 ── 前提(先做这个)
依赖 CVE 监控 + 快速打补丁 / 生产环境不暴露错误详情 / 外部化密钥
P1 ── 最高频事故源
Spring Security 授权(默认拒绝、所有者校验)/ 收敛 Actuator 与管理面暴露
P2 ── 运维卫生
不安全的反序列化 / 请求头、CSRF、会话 / SSRF
| 优先级 | 对策 | 具体做法(Spring Boot) |
|---|---|---|
| P0 | 依赖 CVE 监控 | osv-scanner / dependency-check;按实际运行版本判定,快速打补丁(Log4Shell 类) |
| P0 | 生产错误 | 不要暴露堆栈跟踪(server.error.include-stacktrace=never 等) |
| P0 | 外部化密钥 | 连接信息/密钥从 env/Vault 读取,不硬编码在配置里。不要提交到仓库 |
| P1 | 显式授权 | 默认拒绝 + 方法级授权(@PreAuthorize)+ 所有者校验 |
| P1 | 收敛 Actuator 暴露 | 最小暴露(如 health)+ 强制认证 + 独立端口/边界。不要暴露 env/heapdump |
| P1 | 反序列化 | 不要对不可信数据做原生反序列化。不要让 SpEL 求值输入 |
| P2 | 注入 | 用 JPA/JdbcTemplate 绑定。绝不用字符串拼接构造查询 |
| P2 | 请求头/CSRF/会话 | Spring Security 请求头(HSTS 等)、CSRF、Cookie 属性、会话固定防护 |
| P2 | SSRF | 服务端抓取用白名单限制目标 + 阻断内部 IP/元数据 |
1. 依赖 CVE 与生态(P0)
正因为 Spring 被广泛使用,**一个依赖库的漏洞会一次性波及所有人。**Log4Shell 就是它的象征。
- 用 osv-scanner 或 OWASP dependency-check 机器化监控依赖 CVE,按实际运行版本判定并快速打补丁(以真正构建进去的版本为准,而不是 pom.xml/gradle 的声明)。
- 让 **Spring Boot 和 Java 保持在受支持的版本。**不要把 EOL 版本晾在那里。
- 案例与实务见 Log4Shell 剖析 · 漏洞应对实务手册 · 监控依赖 CVE。
2. 生产配置与密钥(P0)
- 生产环境不要暴露错误详情(堆栈跟踪)—— 减少泄露内部结构和依赖版本的线索。
- 连接信息、密钥等敏感数据要放在 application.properties/yml 之外,从环境变量或密钥管理器(Vault 等)注入。不要提交到仓库(→ .env 文件与密钥)。
- 不要在生产环境启用开发工具(devtools 等)。
3. Spring Security 授权(P1 —— 最高频事故源)
常见(危险)
- 默认宽松,没有按显式放行来设计
- 只用 URL 模式防守,没有方法/所有者校验
- 认证了,但"登录了 = 就允许"
- 配置疏漏让某个端点被放行通过
正确
- 默认拒绝(只有你显式放行的才通过)
- 方法级授权(
@PreAuthorize等)+ 所有者校验 - 在每一条读/改/删路径上校验权限/所有者
- 显式构建授权,不交给默认设置
参见 什么是 IDOR。认证和授权不是一回事;要在贴近数据的地方做授权。
4. Actuator 与管理端点(P1)
- 把暴露的 Actuator 端点收敛到最小(例如仅 health)。
- 强制认证/授权,并放在外部无法到达的独立端口/网络边界。
- 不要暴露
env、heapdump、loggers等敏感端点(信息泄露/操作的跳板)。
5. 不安全的反序列化与表达式求值(P2)
- 不要对不可信数据做原生反序列化(在特定条件下可能导致 RCE)。要校验来源,必要时限制为 JSON 等安全格式(→ 什么是 RCE)。
- 不要让模板或 SpEL 求值用户输入。用 Bean Validation 等校验输入。
6. 注入与数据访问(P2)
- SQL:用 JPA / JdbcTemplate 绑定;绝不用字符串拼接构造查询(→ 什么是 SQL 注入)。
- 从模板输出 HTML 时,要走输出编码,不要直接嵌入用户输入(XSS 防御)。
7. 请求头、HTTPS、会话(P2)
- 用好 Spring Security 的安全请求头(HTTPS 上的 HSTS 等)。用 安全请求头检测 检查自己的站点。
- **强制 HTTPS。**在负载均衡器后面时,配置好让它识别正确的协议/客户端 IP。
- 给 Cookie 设置 Secure/HttpOnly/SameSite,保留 CSRF 保护(浏览器会话默认开启;如果为 API 关闭它,就要搭配替代防护),并在登录时重新生成会话。
8. SSRF 与服务端抓取(P2)
- 服务端抓取用户提供的 URL 时,应把目标限制为白名单,并在连接时阻断到达内部 IP/云元数据(→ 什么是 SSRF)。
验证:你的 Spring Boot 真的加固了吗
做完不等于结束 —— 只有检查过才算完成。以下是针对你自己环境的防御性自查。
Actuator 没有暴露敏感端点
/actuator 没有暴露 env/heapdump 等,并且已启用认证。错误不泄露内部信息
授权确实生效
依赖与请求头
本站观点:地基越坚实,胜负越取决于依赖和暴露面
Spring 是坚实的基础,但正因为它被广泛使用,一个依赖库的漏洞会一次性波及所有人。Log4Shell 就是这一点的象征,而核心防御与其说是某个具体设置,不如说是机器化监控依赖、按实际运行版本判定、快速打补丁的运维习惯。与此同时,把顺手的管理端点(Actuator)从公网暴露面上撤下来,也别把授权交给默认设置。本站是另一套技术栈,但原则完全一致 ——依赖的新鲜度、最小化公网暴露面、显式授权无论用什么框架都有效。
延伸阅读
- 入口:按框架分类的安全 · Next.js 安全
- 案例/实务:Log4Shell 剖析 · 漏洞应对实务手册 · 监控依赖 CVE
- 术语:什么是 IDOR · 什么是 RCE · 什么是 SSRF
- 工具:安全请求头检测
FAQ
Q为 Spring Boot 加固,最先应该做什么?
优先级 P0 的三件事:(1) 机器化监控依赖 CVE 并快速打补丁,按实际运行版本判定(像 Log4Shell 那样,底层库被继承后会一次性波及大量应用,所以跟进速度至关重要);(2) 生产环境不要把错误详情(堆栈跟踪)暴露到外部;(3) 把密钥(连接信息、密钥)外部化,不要硬编码在配置文件里。接下来再推进 Spring Security 授权和收敛 Actuator 暴露。
Q使用 Actuator 时要注意什么?
Actuator 提供运行信息和诊断的管理端点,但一旦暴露就可能泄露内部信息,视配置甚至成为操作的跳板。生产环境应把暴露范围收敛到最小(例如仅 health),强制认证与授权,并放在外部无法到达的独立端口/网络边界。不要暴露 env、heapdump、loggers 等敏感端点。
Q如何防备像 Log4Shell 这样的依赖漏洞?
Log4Shell 是被广泛继承的日志库漏洞一次性波及大量应用的典型案例。防备的关键在于机器化监控依赖 CVE、按实际运行版本判定并快速打补丁(osv-scanner、OWASP dependency-check 等)—— 以真正构建进去的版本为准,而不是 pom.xml/gradle 里声明的版本。最小权限和网络隔离也能缩小爆炸半径。
QSpring Security 授权怎么写才安全?
把默认取向设为拒绝(只有你显式放行的才通过),不要只依赖 URL 模式,在需要处使用方法级授权(@PreAuthorize 等)。在登录(认证)之上,再实现所有者校验,确认目标资源确实属于该用户。配置疏漏会变成提权漏洞,所以授权要显式构建。
Q不安全的反序列化为什么危险?
通过 Java 原生反序列化等方式还原不可信数据,在特定条件下可能导致远程代码执行(RCE)。不要原样还原外部来源的数据,要校验来源,必要时限制为 JSON 等安全格式。同样,也不要让模板或表达式语言(SpEL)去求值用户输入。