SpringSecurity:认证、授权、JWT与接口安全
前言
接口安全不是只在登录接口签发一个 Token,而是覆盖身份确认、访问控制、数据范围、凭证保护和攻击防护的完整链路。本文以 Spring Security 的过滤链为主线,说明 Session、JWT、OAuth2 及接口安全治理在企业系统中的职责边界。
认证、授权与数据权限不是一回事
认证回答“你是谁”,授权回答“你能访问哪个接口或动作”,数据权限回答“你能访问哪些具体订单、租户或部门数据”。Spring Security 主要提供认证和授权框架能力,数据权限仍要在查询条件与业务服务中落实。
flowchart LR
A[HTTP Request] --> B[SecurityFilterChain]
B --> C[Authentication Filter]
C --> D[AuthenticationManager]
D --> E[AuthenticationProvider]
E --> F[SecurityContext]
F --> G[AuthorizationFilter]
G --> H[Controller / Service]
SecurityFilterChain 与认证流程
Spring Security 基于一条或多条 SecurityFilterChain 工作。请求先按 matcher 选择匹配链,再经过认证、异常转换、授权等过滤器。现代 Spring Security 推荐显式声明 SecurityFilterChain Bean,而非旧式继承配置适配器。
认证成功后得到 Authentication,其中包括 principal、权限集合和认证状态,并保存到 SecurityContext。Session 模式通常由 SecurityContextRepository 持久化上下文;Bearer Token 模式一般每次请求解析并验证 Token,不依赖服务端 Session。
| 模式 | 适合场景 | 关键风险 |
|---|---|---|
| Session + Cookie | 同域 Web 后台、服务端渲染 | CSRF、Session 固定攻击、分布式 Session 和注销传播 |
| JWT Bearer Token | 移动端、前后端分离、网关传递身份 | Token 泄露、撤销困难、过期策略、签名算法与 Key 轮换 |
| OAuth2/OIDC | 第三方登录、企业 SSO、资源服务器 | 正确校验 issuer、audience、scope、授权码回调与 PKCE |
JWT 不是“天然更安全”。它是签名的令牌,通常不加密;不要把密码、身份证、完整权限明细等敏感信息放入 payload。验证必须限制允许算法,校验签名、过期时间、issuer、audience,并处理 Key 轮换。高风险注销可用短 access token + refresh token、服务端会话版本/黑名单或 token jti 机制,但要评估存储和一致性成本。
密码、登录和防暴力破解
密码只能保存为带盐的自适应哈希,例如 BCrypt、Argon2 或 PBKDF2,绝不能保存明文、可逆加密或普通 MD5/SHA。使用 PasswordEncoder.matches(raw, encoded) 验证,不能自行比较 hash 字符串。
登录接口还应限制 IP、账号、设备维度的失败次数,使用渐进延迟、验证码或临时锁定,并记录安全审计。错误提示不要区分“用户不存在”和“密码错误”,避免账号枚举。刷新 Token、找回密码、修改手机号等敏感流程需再次验证身份并防重放。
授权:URL、方法与数据
URL 授权适合粗粒度边界,例如公开健康检查、管理员路径、普通登录态接口;方法级 @PreAuthorize 更接近业务动作,例如退款审批。两者应保持一致的权限命名与来源,不能只在 Controller 保护而让 MQ 消费、定时任务或内部调用绕过核心业务授权。
1 |
|
表达式校验不能代替数据权限。查询订单列表时必须在 SQL/Repository 层附加 tenant_id、组织范围或数据归属条件;只校验请求中的 tenantId 等于当前用户输入值没有意义,因为参数来自不可信客户端。
CSRF、CORS 与常见接口风险
CSRF 针对浏览器自动携带 Cookie 的认证模式。Session Cookie 身份的修改类请求应保留 CSRF 防护或采用同站策略和可靠 token 方案;纯 Bearer Token 且不由浏览器自动携带时,CSRF 风险模型不同,但仍要防 XSS 窃取 Token。
CORS 是浏览器同源策略的响应头协商,不是服务端授权。不要配置 Access-Control-Allow-Origin: * 同时允许凭证;应明确可信源、方法、Header 和预检缓存。除此以外还要治理:输入校验、SQL 注入、XSS、SSRF、文件上传、重放、越权、敏感日志和错误信息泄露。
生产配置与排查
| 现象 | 常见原因 | 排查和修复 |
|---|---|---|
| 永远 401 | Token 未传/格式错误、签名 Key 不一致、时钟偏差 | 查看认证失败原因,统一网关和服务时钟,校验 issuer/audience |
| 已登录但 403 | 权限未映射为 GrantedAuthority、URL/方法规则不匹配 | 输出脱敏后的认证主体和权限,检查 matcher 顺序 |
| 预检 OPTIONS 失败 | CORS 配置未在安全链正确处理 | 让 CORS 在 SecurityFilterChain 中生效,明确允许 Header/Method |
| Session 随机失效 | 多实例未共享 Session、负载均衡无粘性或 Cookie 配置错误 | 选择共享 Session 或无状态 Token,检查 SameSite/Secure/Domain |
| 权限放开仍数据越权 | 只有功能权限,没有数据条件 | 在 Repository/Service 层强制租户和归属过滤 |
高频面试题
| 问题 | 回答要点 |
|---|---|
| Spring Security 认证在哪发生? | SecurityFilterChain 的认证过滤器将凭据交给 AuthenticationManager/Provider,成功后保存 Authentication 到 SecurityContext。 |
| 401 与 403 区别? | 401 是未认证或认证无效,403 是已认证但无权限。 |
| JWT 如何注销? | 短 token + refresh token,或服务端维护会话版本/jti 黑名单;不能仅删除客户端 token。 |
| CSRF 为什么主要影响 Cookie? | 浏览器会自动携带 Cookie,攻击站点可诱导修改请求;Bearer Token 通常需脚本主动添加。 |
| RBAC 足够吗? | RBAC 管功能权限,订单、租户、部门等具体数据范围还需要数据权限。 |


