2. 用户身份认证(Authentication):Session-Cookie、JWT、OAuth2.0 在适配层的应用与对比

身份认证,说白了就是回答一个问题:「你是谁?」。在接口适配层,这个问题变得特别棘手——因为你不仅要验证用户身份,还得考虑不同后端系统、不同协议、不同安全等级之间的「翻译」问题。我这些年做接口适配,踩得最多的坑,其实都跟认证有关。

今天咱们就聊聊三种主流认证方式:Session-Cookie、JWT、OAuth2.0。它们在适配层怎么用?各自有什么脾气?我一个个说。

2.1 Session-Cookie:经典但「有状态」

Session-Cookie 是最传统的方案。用户登录后,服务端生成一个 Session ID,存在内存或 Redis 里,同时把 Session ID 通过 Set-Cookie 下发给浏览器。后续请求带上 Cookie,服务端查一下 Session 存储,就知道是谁了。

在适配层用 Session-Cookie,有个天然的问题——有状态。适配层本身是个网关或代理层,如果它要维护 Session 状态,就得引入共享存储(比如 Redis)。否则,请求打到不同的适配实例,Session 就丢了。

我曾经踩过的坑: 有个项目,适配层部署了 4 个节点,Session 存在本地内存里。结果用户登录后,下一个请求被负载均衡转发到另一台机器,直接 302 跳回登录页。排查了半天,最后加了个 Redis 集中存储才解决。

适配层用 Session-Cookie 的场景,我建议这样处理:

  • 适配层不直接管理 Session,而是透传 Cookie 到后端业务服务
  • 如果适配层需要做「登录态校验」,那就统一走 Redis 查询
  • 注意 Cookie 的 Domain 和 Path 属性,别把 Cookie 泄露到不该去的地方
我的习惯: 适配层尽量不做 Session 管理。让后端业务系统自己管 Session,适配层只做「透传 + 校验」。这样适配层保持无状态,水平扩展也方便。

2.2 JWT:无状态,但小心「过期」

JWT(JSON Web Token)这几年特别火。用户登录后,服务端签发一个 Token,里面包含用户信息、过期时间等,客户端存着,每次请求带上。服务端验签就行,不需要查数据库。

适配层用 JWT 有个天然优势——无状态。每个请求都带着完整的身份信息,适配层验签通过后,直接转发。不需要 Redis,不需要 Session 同步。

但 JWT 也有坑。我遇到过最典型的问题:

  • Token 太大:JWT 里塞了一堆用户信息,每次请求都带着,带宽浪费严重
  • 无法主动失效:签发出去的 Token,在过期之前,服务端没法主动让它失效。用户改了密码,旧 Token 还能用
  • 密钥管理:适配层验签需要拿到公钥或密钥,密钥轮换时容易出问题

适配层用 JWT 的最佳实践:

  • Token 里只放必要信息(用户 ID、角色、过期时间),别塞大对象
  • 过期时间别设太长,我一般设 15-30 分钟,配合 Refresh Token 使用
  • 适配层做验签,不做签发。签发交给认证服务
  • 密钥轮换时,适配层要支持多密钥并行验证

代码示例:适配层验签 JWT

// 适配层 JWT 验签示例(Node.js)
const jwt = require('jsonwebtoken');

function verifyToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing token' });
  }

  const token = authHeader.split(' ')[1];
  try {
    // 验签,同时支持多个公钥(密钥轮换)
    const decoded = jwt.verify(token, getPublicKey(token), {
      algorithms: ['RS256'],
      issuer: 'auth-service'
    });
    req.user = decoded;
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid token' });
  }
}

2.3 OAuth2.0:授权协议,别当认证用

OAuth2.0 本质上是个授权协议,不是认证协议。很多人把它当认证用,其实不太对。OAuth2.0 解决的是「第三方应用如何获取用户资源的访问权限」这个问题。

在适配层,OAuth2.0 最常见的用法是:

  • 适配层作为 OAuth2.0 的客户端,向认证服务器获取 Token
  • 适配层验证 Token 的有效性(调用 introspection endpoint)
  • 适配层把 Token 透传给后端服务

我做过一个项目,适配层要对接多个第三方系统的 API,每个系统都有自己的 OAuth2.0 认证流程。适配层得维护多个 Token 的获取、刷新、缓存逻辑。说实话,挺麻烦的。

我曾经踩过的坑: 有个第三方系统的 Token 过期时间只有 5 分钟,适配层没做自动刷新。结果一到高峰期,大量请求因为 Token 过期而失败。后来加了个定时刷新 + 预取机制才搞定。

2.4 三种方式对比

我整理了一张对比表,方便你快速参考:

维度 Session-Cookie JWT OAuth2.0
状态 有状态(需共享存储) 无状态 有状态(Token 需管理)
适配层复杂度 低(透传即可) 中(需验签) 高(需管理 Token 生命周期)
安全性 中(防 CSRF) 高(防篡改) 高(支持多种授权模式)
扩展性 差(需共享存储) 好(无状态) 中(需 Token 管理)
适用场景 单体应用、内部系统 微服务、前后端分离 第三方授权、开放 API

2.5 适配层认证架构图

下面这张图展示了适配层如何处理三种认证方式:

适配层认证架构图 适配层认证处理架构 客户端 API 适配层 认证服务 后端业务服务 请求(带认证信息) 验签 / 校验 Token 验证结果 透传请求 + 用户身份 认证方式处理说明: 1. Session-Cookie:适配层透传 Cookie,不管理 Session 状态 2. JWT:适配层验签,验证通过后提取用户信息,透传给后端 3. OAuth2.0:适配层管理 Token 生命周期,调用 introspection 验证 4. 所有认证方式最终都需将用户身份信息传递给后端服务 5. 适配层不签发 Token,只做验证和透传

2.6 适配层认证选型建议

说了这么多,到底选哪个?我个人的经验是:

  • 内部系统、单体应用:Session-Cookie 够用,别折腾
  • 微服务架构、前后端分离:JWT 更合适,无状态好扩展
  • 对接第三方、开放 API:OAuth2.0 是标准,别自己造轮子
  • 混合场景:适配层可以同时支持多种认证方式,根据请求来源做路由
我的建议: 适配层最好设计成「认证无关」的。也就是说,适配层只做验证和透传,不做认证决策。认证决策交给专门的认证服务。这样,底层认证方式变了,适配层不用改。

嗯,认证这块就聊到这儿。记住一点:适配层的核心职责是「验证身份 + 透传身份」,而不是「管理身份」。把身份管理交给专门的认证服务,适配层保持轻量和无状态,这才是正道。