网站靠「你登录过」记住你是谁,但 HTTP 本身是无状态的——每个请求都是陌生人。接口鉴权要解决的,就是如何在一次次独立请求里,持续、可靠地认出调用方身份,又不被中间人冒名顶替。

一、最古典的:Cookie + Session

早期做法:用户登录,服务器在内存/数据库里建一条 session(存着用户 ID、过期时间),同时给浏览器一个 sessionId 写在 Cookie 里。之后每次请求,浏览器自动带上 Cookie,服务器查 session 认人。

优点:服务端完全掌控(能随时注销、改权限)。缺点:session 要存服务器,用户量一大存储和分布式同步就头疼;且 Cookie 受同源策略管,跨端(比如 App、第三方服务)不方便。

二、Token 的思路:把状态交给客户端

_TOKEN_ 派把「我是谁」的证据直接发给客户端,客户端每次请求在 Header(通常是 Authorization: Bearer xxx)里带着。服务器不存会话,只验证这个 token 真假。天然适合分布式和跨端。

最常见的 token 格式是 JWT(JSON Web Token)。它长得像 xxx.yyy.zzz 三段,分别叫头部、载荷、签名。头部和载荷是 Base64 编码的 JSON(不是加密,谁都能解出来看),签名是用密钥对前两段算出的,用来防篡改。

想亲眼看看一个 JWT 里到底藏了什么,用 JWT 解码器 贴进去,前两段会原样展开——你会发现邮箱、角色、过期时间都明文可见。这恰恰说明:JWT 的载荷别放密码等机密,它只是「签名防篡改」,不是「内容保密」。

三、签名用什么,决定安不安全

JWT 的安全性全在签名。如果用的是对称密钥(HMAC),签发和验证用同一把密钥,服务端得守住它。如果用非对称(RSA/ECDSA),私钥签发、公钥验证,验证方即使拿到公钥也伪造不了 token——适合「A 签发、B 验证」的跨服务场景。

篡改防护的底层也是编码。签名原始字节常做 Base64 再拼进 token,用 Base64 编解码 可以确认某段到底是不是标准 Base64、解出来是什么,排查「token 解析失败」时很实用。

四、过期与刷新

token 不能永久有效,否则泄露了就一直能被用。所以 JWT 通常带 exp(过期时间),短则几十分钟。但为了不逼用户频繁登录,常见搭配是「短 access token + 长 refresh token」:access 过期后用 refresh 换一个新的,refresh 自己存在更安全的存储里、且可被服务端注销。

五、传输与存储的坑

  • 必须走 HTTPS:token 在传输中被截获就等于账号失守,TLS 是底线(详见传输层加密那篇)。
  • 别塞进 URL:token 出现在网址里(比如 ?token=xxx)会被写进日志、浏览器历史、Referer,极容易泄露。用 Header 传。URL 里的特殊字符还要编码,用 URL 编码工具 看编码差异能定位「传过去变了样」的问题。
  • 前端存哪:SPA 存 localStorage 方便但易受 XSS 偷;存内存更安全但刷新就没。没有完美方案,配合严格的 CSP 和输入转义降低 XSS 风险是关键。

六、OAuth2 与「第三方登录」

你点「用微信登录」,背后是 OAuth2:你授权某应用「代我访问我在微信的部分信息」,微信发给它一个 access token,它拿这个 token 去取你的昵称头像。核心是「授权」而非「把密码给第三方」——第三方永远拿不到你的微信密码。

七、怎么选

  • 传统单体 Web、要强管控会话 → Cookie/Session 仍合适。
  • 分布式 API、移动端/第三方调用 → Token/JWT 更顺。
  • 跨服务且要防验证方伪造 → 非对称签名的 JWT。
  • 接入第三方账号 → OAuth2。

无论哪种,三条铁律不变:传输加密、密钥守好、令牌有过期与注销机制。

小结:鉴权是在无状态 HTTP 上持续认人。Cookie/Session 把状态留服务端、好管控;Token/JWT 把证据给客户端、好扩展。JWT 签名防篡改但载荷不保密,别放机密、必须 HTTPS、别进 URL。方案可组合,安全底线不变。