Java程序员的鉴权江湖:Session 与 JWT 的爱恨情仇
HTTP 是健忘的,而程序员是执着的。
我们为让服务器记住用户,造出了两种记忆体系:Session——稳重老派;JWT——灵动新潮。
一个靠“查档案”,一个靠“签契约”。
一、鉴权的核心哲学
HTTP 是无状态的,每一次请求都是陌生人上门:
“我是谁?你凭什么信我?”
于是程序员发明了两种记忆机制:
| 流派 | 思想核心 |
|---|---|
| Session 派 | 服务端保存状态:我记得你是谁。 |
| JWT 派 | 客户端自带凭证:你自己证明你是谁。 |
无论选哪派,核心过程都一样:
- 用户登录成功,获得凭证。
- 每次请求带上凭证。
- 服务端验证凭证是否可信。
二、Session:服务器的温柔记忆
🌱 单机版原理与代码
1 | // 登录接口示例 |
🔁 Session 生命周期
创建阶段: 第一次调用
getSession()。活跃阶段: 每次请求自动刷新过期时间。
销毁阶段:
- 超时未访问(默认30分钟)。
- 主动调用
session.invalidate()。 - 服务器重启或内存清除。
配置示例:
1 | server.servlet.session.timeout: 60m |
⚙️ 分布式 Session:共享记忆
单机没问题,但一旦负载均衡——
1 | 用户第一次访问 -> Server A(创建Session) |
解决方案三选一:
| 方案 | 思路 | 优点 | 缺点 |
|---|---|---|---|
| Session复制 | 节点同步Session | 应用透明 | 同步代价大 |
| 粘性会话 | 用户固定访问同一节点 | 实现简单 | 容灾差 |
| Session共享(推荐) | 使用Redis集中存储Session | 稳定可扩展 | 有外部依赖 |
Redis共享Session示例:
1 | <dependency> |
1 | spring: |
Redis 实际存储内容:
1 | spring:session:sessions:abc123 -> {"user":"neo", "expireTime":1736971200000} |
❓Session 必须放在 Cookie 吗?
不一定。
| 方式 | 说明 | 优点 |
|---|---|---|
| Cookie(默认) | 浏览器自动携带 | 简洁,安全性高,可加 HttpOnly、Secure |
| Header | 手动在请求头中传递 Authorization: Session abc123 |
适合跨域和移动端 |
| URL 参数 | ?sid=abc123 | ⚠️ 极不安全,禁止用于生产 |
✅ 结论:SessionID 只是凭证,可以放任何地方,只要服务端能取到即可。
Cookie 不是必须的,只是“最懂浏览器的信使”。
三、JWT:客户端的自由契约
JWT(JSON Web Token)主张:
“状态我自己带,信任靠签名。”
🧩 结构拆解
JWT由三部分组成:
1 | Header.Payload.Signature |
Header:说明算法与类型,例如:
1
{"alg": "HS256", "typ": "JWT"}
Payload:承载用户数据:
1
{"sub": "neo", "role": "admin", "exp": 1760978291}
Signature:签名,防止被篡改。
生成Token示例:
1 | String token = Jwts.builder() |
验证Token:
1 | try { |
🔐 JWT 进阶用法
- 自定义 Claim: 添加业务信息,如用户ID、登录设备。
- Token 刷新机制: Access Token + Refresh Token 双Token模式。
- 黑名单策略: Redis存储已登出的Token,防止重放攻击。
黑名单验证示例:
1 | if (redisTemplate.hasKey("blacklist:" + token)) { |
四、Session vs JWT:同源不同命
| 对比项 | Session | JWT |
|---|---|---|
| 存储位置 | 服务端(内存/Redis) | 客户端(Token中) |
| 状态管理 | 有状态 | 无状态 |
| 主动失效 | ✅ 可删Session | ❌ 需黑名单 |
| 分布式支持 | 需共享Session | 天然支持 |
| 安全性 | 高(服务端控制) | 中(签名验证) |
| 性能 | 需查存储 | 快,直接验签 |
| Token大 | 小 | 大 |
Session 是“记得你”;JWT 是“信你自己”。
五、实战选型建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 单体系统 | Session | 简单稳健 |
| 分布式系统 | Redis Session | 高可用、低风险 |
| 前后端分离 | JWT | 无状态、跨域支持 |
| 高安全要求 | JWT + Redis黑名单 | 可控失效机制 |
| 大型SSO | JWT + 刷新机制 | 标准、可扩展 |
六、尾声:记忆与契约的两种浪漫
Session 像个老和尚——稳重、可靠,凡事记在心头;
JWT 像个浪子——自由、签约、无拘无束。
真正的高手不是选谁,而是清楚:
- 凭证放哪?
- 状态存哪?
- 何时让它失效?
HTTP 或许无情,但程序员让它有了“记忆”。
因为被记住,本身就是一种浪漫。
Comments




