第4章 认证机制:OAuth2.0、JWT、Session vs

说到接口认证,我最早是从 Session 开始入门的。那会儿做一个企业后台,session 一把梭,感觉挺爽。直到后来接手一个移动端项目,遇到了跨域、Session 无法共享的问题,才意识到——嗯,不同场景必须用不同的认证方案。

Session 与 :状态在谁手里?

Session 和 的核心区别,说白了就是「认证状态放哪」。Session 把状态存在服务端内存或 Redis 里,客户端只存一个 sessionId。 则把用户身份信息签名后直接发给客户端,服务端不保存会话。

我个人习惯:如果是纯服务端渲染的传统应用,Session 仍然是最简单的;一旦涉及多端、微服务或第三方接入,直接上 。

我曾经在一个电商系统中混用两种方案,结果发生 session 与 认证双重校验的 bug,排查了整整半天。从那以后我定了一个原则:一个项目只选一种主认证方式,不要混搭。

维度 Session
存储位置 服务端(内存/Redis) 客户端(localStorage/Cookie)
扩展性 需要集中式 Session 存储 天然无状态,容易水平扩展
跨域支持 依赖 Cookie,跨域麻烦 HTTP Header 携带,跨域友好
安全性 服务端可控,可主动销毁 令牌泄露后难立即失效

JWT:自包含的令牌

JWT(JSON Web )是目前最主流的 实现。它的体积小,可以携带用户基本信息,而且签名保证了完整性。为什么工程界都喜欢它?因为它能帮我们省掉一次数据库查询——服务端拿到 JWT 一验签名,就知道你是谁。

关键点:JWT 是“签名防篡改”而不是“加密防窥探”。如果你在 Payload 里放身份证号,那客户端一看 Base64 解码就全知道了。我见过有人把密码明文放 JWT 里,直接崩溃。

我在项目里遇到过两次 JWT 被重放的案例。客户端拿到 JWT 后,只要没过期,哪怕是别人偷用的也能正常请求。解决方案是搭配 jti(JWT ID)和黑名单机制,或者用短时效 + 刷新令牌的组合。我的建议:JWT 的过期时间不要超过 15 分钟,再配合 Refresh 来做续期。

// 一个标准的 JWT 结构示例
// Header
{
  "alg": "HS256",
  "typ": "JWT"
}
// Payload
{
  "sub": "1234567890",
  "name": "张三",
  "iat": 1516239022,
  "exp": 1516242622
}
// Signature: HMACSHA256(
//   base64UrlEncode(header) + "." +
//   base64UrlEncode(payload),
//   secret
// )

OAuth2.0:授权框架

很多人把 OAuth2.0 和 JWT 混为一谈,其实它们是两个层面的东西。OAuth2.0 是一种授权协议,它解决的是「第三方应用如何安全地访问用户资源」。而 JWT 只是其中一种令牌格式,OAuth2.0 也可以使用其他令牌(比如不透明字符串)。

记得我做开放平台时,最头痛的是授权码流程(Authorization Code Flow)的 code 与 交换环节。有一次因为 redirect_uri 没有校验严格,被安全团队打回来整改。大家要记住:OAuth2.0 里 redirect_uri 必须完全匹配,不能写通配符。

警惕:Never 在客户端的 Implicit 模式中返回 access_(RFC 6749 已弃用这种模式)。现在官方只推荐授权码模式 + PKCE 扩展。

我个人在实践中坚持使用授权码模式(Authorization Code)并加上 PKCE。特别是移动端或单页应用,没有客户端密钥,PKCE 能防止授权码被截获后冒用。具体流程:

  1. 客户端生成一个 code_verifier 并计算 code_challenge
  2. 用户授权后服务端返回授权码
  3. 客户端用授权码 + code_verifier 换
  4. 服务端校验 code_verifier 是否匹配 code_challenge

认证方案选型决策图

下面这张图帮你理清 Session、、JWT 和 OAuth2.0 的关系。红色是核心概念,蓝色表示有状态方案,绿色表示无状态方案,紫色和橙色分别是 JWT 和 OAuth2.0 的位置。

认证机制选型关系图 认证机制 有状态 无状态 Session 服务端存储 客户端存储 JWT 自包含令牌 OAuth2.0 授权框架 选型建议: 单体应用用 Session;多端/微服务用 JWT;第三方授权场景直接用 OAuth2.0

如何选型?一张表搞定

你可能会问:这么多方案,我到底该用哪个?别急,我整理了一张实践对照表,按常见场景给出推荐:

场景 推荐方案 理由
内部管理系统(B/S) Session + Cookie 简单可控,服务端能主动踢人
移动端 App(原生) JWT + Refresh 无状态,便于多设备;短 防重放
单页前端 + API JWT(短时效) + oauth2 PKCE 无 cookie 跨域问题;PKCE 防授权码截获
第三方开放平台 OAuth2.0 授权码模式 标准协议,第三方无需信任你的密码
微服务间通信 JWT(内部 ) 自包含,网关校验后直接传给下游

避坑指南:我曾经在一个微服务项目里,所有服务共用同一个 JWT Secret。后来一个业务服务被挖出漏洞,攻击者拿到 secret 后伪造了任意用户的 。血的教训——微服务之间应该使用独立的 JWT secret,或采用不对称签名(RS256)。

最后提一嘴,Session 不是万能的, 也不是银弹。理解每种方案背后的 trade-off,比盲目追逐新技术重要得多。你想想看,一个简单的工单系统用 OAuth2.0 套来套去,何必呢?