JWT 与 OAuth:关键区别、协作方式与最佳实践
一份简明指南,解释了 JWT 和 OAuth 之间的区别,它们如何相辅相成,以及如何有效地使用这两者的最佳实践。
如果你刚接触身份验证,正在开发处理登录、支付或用户数据的应用,那么你很可能遇到过 JWT 和 OAuth 这些术语。它们听起来像是复杂的“后端专用”话题,但其实不仅仅是安全工程师才需要了解它们。
在 API、第三方集成,以及像 AI、MCP、基于代理的系统等新兴技术场景中,这两者对你的产品可用性、安全性及增长有直接影响。掌握基础知识意味着你可以:
- 从一开始就设计安全的功能
- 与你的工程团队高效沟通
- 关于认证与用户流做出更好的产品决策
- 避免因安全失误而导致的用户信任损失与高额代价
例如,在最新的 MCP 规范 中,授权系统基于成熟标准构建:
- OAuth 2.1 IETF 草案(draft-ietf-oauth-v2-1-13)
- OAuth 2.0 授权服务器元数据(RFC8414)
- OAuth 2.0 动态客户端注册协议(RFC7591)
- OAuth 2.0 受保护资源元数据(RFC9728)
为什么这很重要
即使你从不写后端代码:
- 开发者可以了解如何保护 API、安全管理会话、以及集成第三方服务。
- 产品经理获得讨论登录流程、集成与合规性的专业词汇,便于和团队及合作伙伴沟通。
- 创始人与早期团队避免构建那些集成时容易崩溃或存在安全漏洞的脆弱登录系统。
JWT vs OAuth:两个核心概念
JWT(JSON Web Token,JSON 网络令牌)与 OAuth(开放授权)经常搭配使用,但它们各自的作用不同。
可以这样理解:
- OAuth 是 你如何把钥匙交给别人,但只允许进入他们该去的房间。
- JWT 是 他们携带的身份证,证明他们是谁以及拥有什么权限。
接下来,我们会并列拆解两者,让你清楚看到它们的不同及如何相辅相成。
什么是 OAuth 2.0?
OAuth 2.0 是广泛采用的授权框架,它让应用(客户端)能以有限权限访问用户资源,无需让用户暴露自己的凭据(如密码)。
OAuth 的核心角色
- 客户端: 请求访问的应用。
- 资源所有者: 通常指用户,给予权限。
- 授权服务器: 授权后颁发访问令牌。
- 资源服务器: 托管受保护资源并验证令牌。
常见 OAuth 授权类型(流程)
- 授权码授权(Authorization Code Grant): 最安全、最推荐,特别是配合 PKCE,用于浏览器、单页应用和移动端。
- 隐式授权(Implicit Grant): 出于安全考虑,在 OAuth 2.1 中已不推荐。
- 资源所有者密码凭据(ROPC): 直接用用户名和密码换取令牌;安全性较低。
- 客户端凭据授权(Client Credentials Grant): 用于服务器间沟通或机器对机器(M2M)场景。
- 设备码流程(Device Flow): 用于无键盘设备(如智能电视),用户通过第二设备授权。
什么是 JWT(JSON Web Token)?
JWT 是开放标准(RFC 7519),用于在两方之间以紧凑、URL 安全的方式安全传递声明(claims)。
JWT 的结构
JWT 由三部分 base64url 编码内容组成,用点号(.)分隔:
- 头部(Header): 指定算法(如 HS256、RS256)及令牌类型(JWT)。
- 负载(Payload): 承载各类声明,例如:
- iss(发行者)
- sub(主题,如用户 ID)
- aud(受众)
- exp(过期时间)
- 需要时自定义声明
- 签名(Signature):确保令牌未被篡改。
例如:
一个 JWT 示例
下面是一个典型 JWT 的编码形式,以及对应解码结构,让你理解每部分的含义。
编码 JWT(Base64URL)
它由三部分通过点号分隔:header.payload.signature
解码结构
- 头部
- 负载
负载部分存放着声明。
- 签名
签名保证了令牌未被篡改。
主要 特点
- 自包含: 所有必要信息都在令牌之中。
- 无状态: 不需要服务器端会话存储。
- 签名:(可选加密)确保真实性。
JWT 与 OAuth:核心区别
方面 | JWT | OAuth 2.0 |
---|---|---|
定义 | 令牌格式 | 授权框架 |
作用 | 安全承载身份/声明 | 定义授权与访问管理流程 |
范围 | 数据表达 | 流程与机制 |
能独立使用? | 可以,仅用于自有令牌处理 | 不行,需要令牌格式(如 JWT) |
示例用途 | API 直接向客户端签发 JWT | 应用通过 OAuth 流程获得访问令牌 |
简而言之:
- JWT 是容器: 就像一本载有身份信息的护照。
- OAuth 是系统: 就像出入境管理,决定谁能拿护照、能访问什么。
何时单独使用 JWT
当出现以下情况时可单独用 JWT:
- 单一系统认证:应用自发行并校验令牌,无需外部身份提供方。
- 无状态会话管理:无需在服务器存储会话即可校验用户身份。
- 简单 API 认证:内部 API 只需验证基础访问权限,无需复杂同意流程。
- 性能优先校验:资源服务器本地即可校验令牌,无需请求认证服务器。
示例:
你自有的单页应用和后台 API。API 向客户端签发包含 sub(用户 ID)、role、exp(过期时间)声明的 JWT。
何时单独使用 OAuth
单独用 OAuth(不配合 JWT)时:
- 不要求令牌自包含,可接受需查找的 opaque token(不透明令牌)。
- 希望资源服务器每次访问都向认证服务器核查。
- 处于旧系统或受监管环境,JWT 方案不适用。
- 重点是安全地实现对第三方应用的委托授权。
示例:
API 签发不透明访问令牌,并在每次请求时询问授权服务器验证。
何时同时使用 JWT 与 OAuth
需要二者同时搭配时:
- 你有多个服务或 API,需要 OAuth 实现安全授权流程、用 JWT 做可校验的跨服务凭证。
- 提供第三方登录(比如“使用 Google 登录”),OAuth 负责同意流程,JWT 携带访问令牌或 ID 令牌。
- 采用微服务架构,各服务本地即可校验 JWT。
- 需要 OAuth 的委托模型与 JWT 的无状态验证实现可扩展性。
示例:
你的应 用允许通过 Google 登录。OAuth 管理授权流程,Google 发放 JWT 类型访问令牌,你的 API 本地校验证明后返回数据。
JWT 和 OAuth 的协作方式
现代认证/授权环境下:
- OAuth 管理授权流程。
- 授权服务器 签发访问令牌:通常为 JWT。
- JWT 随 API 请求发送,证明身份与权限。
OAuth 中的特殊令牌
使用 JWT 和 OAuth 的最佳实践
- 使用 HTTPS 保护令牌在传输过程中的安全。
- 设置 JWT 较短的有效期,长会话用刷新令牌。
- 在信任声明前先校验签名。
- 校验 aud 声明,确保令牌发给你的应用。
- 如果有 XSS 风险,避免将令牌存储在 localStorage,优先使用安全的 Cookie。
总结
- OAuth 2.0 定义了如何获取与使用令牌。
- JWT 定义了令牌长什么样、如何承载信息。
- 它们是互补而非可互换的。
大多数现代 API 都用 OAuth 实现授权流程,用 JWT 作为令牌格式。理解两者原理能助你设计安全、易扩展的认证系统。