安全这个问题,很多 Java 面试都喜欢问。一个朋友去面 Java 高级开发,前面聊 JVM、Redis、MySQL 都挺顺,结果面试官忽然抛出一句:“如果让你负责一个 Spring Boot 项目,你会如何保证应用程序的安全性?”
朋友心想,这题不是白送吗?张口就答:“用 Spring Security!” 面试官点了点头,又补了一句:“然后呢?” 空气突然安静了。
其实这道题考察的,并不是你知不知道 Spring Security 这个名字,而是你心里有没有一套完整的 Web 应用安全体系。今天我们就顺着这个问题,把 Spring Boot 安全设计从头理一遍。
先别急着写代码,我们先开一家公司
假设我们开了一家互联网公司,园区里有研发楼、财务室、机房和老板办公室。员工想要进园区,第一件事是什么?当然是证明“我是谁”。
保安检查工牌,确认你是不是本公司员工,这就是 Authentication,认证。可进了大门之后,是不是所有区域都能随意进出?显然不是。普通程序员能进研发楼,但不能进财务室;运维工程师能进机房,普通员工却不能随便进去。
这时候要解决的问题就变成了“你能干什么”,也就是 Authorization,授权。理解 Spring Boot 安全体系,先得把这两个核心概念分清。

Spring Security 最核心的工作,就是围绕认证和授权建立一道道安全防线。这里说的不只是一个框架,更是整个请求进入系统之前要经过的完整安全链路。
Spring Security 就像公司的安保中心
在 Spring Boot 项目里,最常见的落地方式就是引入 Spring Security。以 Maven 为例,先加上依赖:

但比依赖更重要的是:请求到底是怎么被保护起来的?
Spring Security 并不是等请求进入 Controller 之后才检查权限,它更像在公司大楼门口修了一条“安检通道”。一个 HTTP 请求进入应用时,大致要经历这些环节:

这里最关键的概念就是 SecurityFilterChain。Spring Security 本质上是靠一系列 Filter 来完成安全处理的:有的负责登录,有的负责读取安全上下文,有的负责异常处理,还有的负责授权。
所以如果面试时只说“Spring Boot 用 Spring Security 实现安全”,只能算刚入门。要是能接着解释“Spring Security 基于 Servlet Filter 构建安全过滤器链,在请求进入业务 Controller 前完成认证、授权以及相关安全处理”,整体印象会完全不一样。
第一道门:认证
假设用户请求 GET /api/orders,服务器首先要搞清楚:这个人是谁?
传统 Web 项目常用 Session。用户第一次登录时:

后续请求携带 Cookie,服务器根据 SessionId 找到用户信息。
不过现在很多 Spring Boot 项目都是前后端分离架构,更常见的方案是 JWT Token,流程大概是:

这就像公司取消了纸质访客登记,改成发一张电子门禁卡,每次进门刷一下就行。但这里有个特别容易被忽略的点:JWT 不是“加密用户数据”的代名词。
常见 JWT 的 Payload 只是 Base64URL 编码,并不等于加密。所以千万不要把密码、银行卡号等敏感信息塞进去。
第二道门:授权
身份确认之后,还得检查权限。比如系统中有普通用户 USER 和管理员 ADMIN 两种角色,我们可以这样配置:

这就相当于:/login 游客也能进,/admin/** 需要管理员门禁,/user/** 普通员工或管理员都可以进,其他接口至少得先证明身份。
对于更细粒度的权限控制,还可以使用方法级权限:

这样权限就从“你是什么角色”进一步变成“你到底有没有执行这个动作的权限”。大型后台系统里,通常会采用 用户 → 角色 → 权限 的经典 RBAC 模型:

比起在代码里到处判断 role == ADMIN,这种权限模型的可扩展性显然更好。
密码千万不能明文保存
有些项目安全设计看起来很豪华:JWT 有了,Spring Security 有了,RBAC 也有了。结果打开数据库一看,password: 123456,直接明文存储。这就好比你花几十万装了门禁系统,转头把保险柜密码贴在了保险柜门上。
Spring Security 通常使用 BCrypt 来处理密码:

保存密码时:

登录验证时使用:
passwordEncoder.matches(rawPassword, encodedPassword);
BCrypt 的一个重要特点就是使用随机盐,所以即使两个用户的密码都是 123456,最终得到的哈希值通常也不一样。
还有一点要明确:密码安全的正确思路不是“加密以后再解密”,而是密码 → 单向哈希 → 保存。登录时做的是验证,不是把原始密码还原出来。
HTTPS:别让门禁卡在路上被复制
身份认证做得再好,如果客户端和服务器之间的通信不安全,敏感信息照样可能暴露。生产环境通常应该启用 HTTPS。
HTTPS 通过 TLS 提供传输加密、完整性保护和服务器身份认证。简单理解就是:以前用户和服务器之间传消息像寄明信片,路上的人都能看到内容;HTTPS 更像把内容装进受保护的信封,同时还要确认对面确实是目标服务器。
尤其是登录密码、Token、支付信息等敏感数据,更不应该裸奔在不安全的传输链路上。
CSRF 和 CORS,别傻傻分不清
这两个概念面试中特别容易混。先说 CSRF。
假设你已经登录了银行网站,浏览器里保存着 Cookie。这时你访问了一个恶意网站,对方偷偷发起 POST /transfer。如果浏览器自动携带银行 Cookie,而服务器又没有额外防护,就可能发生跨站请求伪造,也就是 CSRF,Cross-Site Request Forgery。
Spring Security 默认提供 CSRF 防护,但很多前后端分离、使用 Bearer Token 且不依赖浏览器自动携带认证 Cookie 的 API,需要根据实际认证机制重新评估是否需要 CSRF 防护,而不是看到教程就机械地 csrf.disable();。
再说 CORS。CORS 解决的是:浏览器是否允许某个来源的前端页面读取另一个来源的响应。比如前端在 https://www.example.com,后端在 https://api.example.com,就需要正确配置跨域策略。

记住一条:CORS 不是身份认证机制,也不能代替 CSRF 防护。
真正的安全不能只靠 Spring Security
讲到这里,可能有人觉得 Spring Security 配完就万事大吉了。当然不是。它更像公司的门禁系统,但一家公司的安全不能只有门禁。
比如接口还要考虑 SQL 注入。不要直接拼接 SELECT * FROM user WHERE name = '" + name + "' 这类语句,而应该优先使用参数绑定。文件上传也不能只判断后缀名——avatar.jpg 不代表它真的就是图片,还需要考虑文件类型、大小、存储位置、随机文件名以及访问权限等问题。
另外还要防止暴力破解。如果一个登录接口允许攻击者 1 秒尝试 1000 次密码,再复杂的认证流程也可能遭遇撞库或密码爆破。因此可以增加登录失败次数限制、IP/用户维度限流、验证码、异常行为检测、短时间冻结等措施。
安全从来不是一个组件,而是一整套体系。
Token 也不是拿到以后就万事大吉
还有一个特别容易被忽略的问题:Token 生命周期。如果 JWT 有效期设成一年,一旦 Token 泄露,风险窗口就会非常长。成熟系统通常会设计 Access Token + Refresh Token 的双 Token 方案:Access Token 生命周期较短,用来访问接口;Refresh Token 生命周期较长,用于获取新的 Access Token。
对于退出登录、修改密码、账号冻结等场景,还需要根据业务安全要求设计 Token 撤销、版本号、黑名单或者服务端会话状态等机制。这也解释了为什么“用了 JWT”不等于“实现了安全”——JWT 只是认证体系中的一种凭证方案。
生产环境还要保护 Actuator
Spring Boot 项目经常使用 Actuator 做健康检查和监控,比如 /actuator/health、/actuator/metrics、/actuator/env。这些端点非常有价值,但如果配置不当,也可能成为敏感信息的泄露口。
生产环境应遵循最小暴露原则,只开放真正需要的 Endpoint,同时通过网络隔离、认证授权等方式限制敏感管理接口。否则就像把“服务器机房运行手册”直接贴在大门口。
面试官真正想听的是“纵深防御”
现在再回到最开始的问题:如何实现 Spring Boot 应用程序的安全性?
如果让我在面试中回答,我不会只说 Spring Security,而是把它拆成几个层次:

每一层都有自己的职责:

这里还有一个特别重要的原则:最小权限原则。用户只获得完成工作所需要的权限,数据库账号也是一样。如果应用程序只需要 SELECT INSERT UPDATE,就没必要给它 DROP DATABASE。别让一个送外卖的小哥,因为需要进公司大门,就顺手拿到了机房钥匙。
最后再聊一个容易被忽略的东西:日志
安全系统如果没有日志,就像公司装了监控却没有录像。对于用户登录、登录失败、修改密码、权限修改、删除数据、资金操作、管理员操作、Token 异常等关键操作,应该建立合理的审计日志。
但日志也不是越详细越好。千万不要直接打印用户密码、完整 Token、银行卡号、身份证号、密钥、数据库密码等信息,否则日志系统本身反而会变成新的数据泄露源。安全日志讲究的是:该记录的记录,该脱敏的脱敏。
总结
Spring Boot 应用安全并不等于“Spring Security = 安全”,而应该理解成:安全 = 认证 + 授权 + 密码保护 + HTTPS + CSRF/CORS/XSS 防护 + 输入校验 + 接口限流 + Token 生命周期管理 + 最小权限 + Actuator 保护 + 密钥管理 + 日志审计 + 依赖漏洞治理。
Spring Security 只是其中非常核心的一环。真正成熟的系统采用的是 Defense in Depth——纵深防御。就像保护一座城,不是修一堵城墙就结束了,而是要有护城河、城门、守卫、巡逻队、身份令牌、内部禁区以及事后的监控和审计。
所以下次面试官再问“如何保证 Spring Boot 应用程序的安全性”,千万别只回答一句“引入 Spring Security”。真正有经验的工程师考虑的应该是:请求是谁发来的?他能访问什么?数据在路上安全吗?凭证泄露怎么办?接口能不能被攻击?内部权限有没有越界?出了安全问题以后能不能追踪?
当你开始从这些问题思考时,讨论的就不再只是一个框架,而是一套完整的应用安全体系。
如果你希望把这套安全体系系统性地学透,Spring Security 从入门到精通 会从表单登录、授权、RememberMe 持久化到 CSRF 防御逐层拆解,并结合 Spring Boot、MyBatis、JPA 和 Vue 演示企业级 Web 安全架构的落地方式。
