Session 与 JWT 认证如何选型?无状态认证方案如何设计?

结论先行:Session 认证把状态存在服务端(内存/Redis),客户端只持会话 ID,优点是可随时失效、可控性强;JWT 把用户信息与签名放进客户端令牌,服务端无状态、天然适合水平扩展,代价是签发后难立即撤销、载荷越长体积越大。微服务/前后端分离常用短时 JWT + refresh token 组合,纯内网/强管控场景仍可回归 Session。

一、两种方案对比

维度SessionJWT
状态存放服务端(内存/Redis)客户端(无状态)
扩展性需共享存储/粘性会话任意节点可验签
失效控制删 Session 即失效难撤销,等过期/黑名单
安全注意CSRF(Cookie 自动携带)XSS(localStorage 存储)、密钥泄露
适合场景单体、内网、强管控微服务、跨域、开放 API

二、JWT 结构

header.payload.signature
// header: {"alg":"HS256","typ":"JWT"}
// payload: {"sub":"1001","exp":1700000000,"scope":"read"}
// signature: HMACSHA256(base64(header)+"."+base64(payload), secret)
  • 三部分:头部(算法)、载荷(声明)、签名(防篡改);
  • 典型做法:登录校验通过后用密钥签发 access token(1530 分钟),另发 refresh token(数小时数天);
  • 验签在网关或资源服务完成:本地解析 + 验签即可,不查库,这是“无状态”的核心。

三、无状态认证设计要点

  1. 令牌携带方式:Authorization: Bearer <token>不放 URL
  2. 客户端存储:优先 httpOnly + Secure Cookie(防 XSS 读取),避免 localStorage;
  3. 刷新与续期:access 过期用 refresh token 换新,refresh 需可吊销(存 Redis 白/黑名单);
  4. 服务端解析:自定义 OncePerRequestFilter → 解析验签 → 把 Authentication 写入 SecurityContext;
  5. 主动失效手段:维护 jti 黑名单、缩短过期时间、改密钥强制全员失效;
  6. 敏感操作二次校验:JWT 只能证明“曾登录”,高危接口仍建议验密码/验证码。

常见追问 / 记忆点

  • 追问:JWT 为什么难实现“踢人下线”?答:令牌由客户端自持,服务端无状态即无撤销点,需黑名单或缩短有效期补偿。
  • 追问:Session 一定比 JWT 慢吗?答:单体上差距很小;瓶颈在分布式共享存储与序列化,JWT 免查询但多付带宽与验签成本。
  • 记忆点:Session 强在可控、JWT 强在无状态;生产多用“短 JWT + refresh + 必要黑名单”的折中。
笔记加载中…