3. 鉴权模式概览:API Key、Bearer Token (JWT)、OAuth2.0、Basic Auth 原理对比
在构建 OpenAPI 网关或中间件时,选择正确的鉴权模式是保障系统安全的第一道防线。不同的鉴权机制在安全性、易用性、可扩展性和适用场景上存在显著差异。本章将从原理层面对四种主流模式进行深度对比,帮助你在架构选型时做出精准决策。
核心认知:鉴权(Authentication)≠ 授权(Authorization)。本章讨论的四种模式主要解决“你是谁”的问题,而 OAuth2.0 在授权层面提供了更丰富的流程。理解这一区别是掌握后续中间件配置的基础。
3.1 四种鉴权模式核心原理
3.2 四种模式详细对比
| 对比维度 | API Key | Bearer Token (JWT) | OAuth2.0 | Basic Auth |
|---|---|---|---|---|
| 传输方式 | 请求头 / 查询参数 | Authorization: Bearer <token> | Authorization: Bearer <access_token> | Authorization: Basic <base64> |
| 令牌格式 | 固定字符串 | JWT (三段式) | 不透明 / JWT | Base64(username:password) |
| 状态管理 | 无状态 | 自包含(无状态) | 有状态(授权服务器) | 无状态 |
| 过期机制 | 手动轮换 | 内置 exp 声明 | Access Token + Refresh Token | 无(需修改密码) |
| 安全等级 | 中 | 中高 | 高 | 低(需 HTTPS) |
| 适用场景 | 内部服务、简单 API | 微服务、单点登录 | 开放平台、第三方授权 | 测试环境、内部工具 |
| 实现复杂度 | 低 | 中 | 高 | 极低 |
3.3 深入理解各模式原理
3.3.1 API Key:最简单的静态令牌
API Key 是一种预共享的静态字符串,服务端在创建时将其与特定客户端绑定。每次请求时,客户端将 Key 放入请求头(如 X-API-Key)或查询参数中。服务端通过查找预存列表进行匹配验证。
中间件处理要点:
- Key 的存储必须加密(如 bcrypt 哈希),避免明文泄露
- 支持 Key 的轮换机制,防止长期使用同一 Key 带来的风险
- 建议限制 Key 的权限范围(如只读/读写)
3.3.2 Bearer Token (JWT):自包含的令牌
JWT 由三部分组成:Header(算法声明)、Payload(用户信息、过期时间等声明)、Signature(防篡改签名)。服务端通过验证签名确认令牌有效性,无需查询数据库。
// JWT 结构示例
// Header
{
"alg": "HS256",
"typ": "JWT"
}
// Payload
{
"sub": "user_12345",
"name": "张三",
"iat": 1718000000,
"exp": 1718003600,
"role": "admin"
}
// Signature
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret_key
)
安全警告:JWT 的 Payload 仅经过 Base64 编码,并非加密。切勿在 Payload 中存储密码、信用卡号等敏感信息。必须使用 HTTPS 传输,防止中间人截获。
3.3.3 OAuth2.0:授权框架的四种模式
OAuth2.0 不是一个单一的鉴权协议,而是一个授权框架。它定义了四种授权模式,每种模式适用于不同的客户端类型。
- 授权码模式(Authorization Code):最安全,适用于有后端的 Web 应用。流程包含授权码交换步骤,避免令牌直接暴露在浏览器中。
- 隐式模式(Implicit):适用于纯前端应用(已逐渐被 PKCE 取代),直接返回 Access Token。
- 密码模式(Resource Owner Password Credentials):用户直接提供用户名密码给客户端,仅适用于高度信任的第一方应用。
- 客户端凭证模式(Client Credentials):适用于服务到服务的通信,无需用户参与。
3.3.4 Basic Auth:最原始的 HTTP 认证
Basic Auth 将用户名和密码以 username:password 格式拼接后,进行 Base64 编码,放入 Authorization 请求头中。由于 Base64 是可逆编码,本质上等同于明文传输。
// Basic Auth 请求头示例
// 原始凭证: admin:secret123
// Base64 编码: YWRtaW46c2VjcmV0MTIz
Authorization: Basic YWRtaW46c2VjcmV0MTIz
生产环境禁忌:Basic Auth 必须配合 HTTPS 使用,否则凭证在传输过程中可被任意中间节点截获。即使使用 HTTPS,也建议仅在内部网络或测试环境中使用。
3.4 中间件选型决策指南
| 业务场景 | 推荐模式 | 理由 |
|---|---|---|
| 内部微服务通信 | JWT / API Key | 无状态、低延迟、易于实现 |
| 开放 API 平台 | OAuth2.0 | 支持第三方授权、细粒度权限控制 |
| 移动端 / SPA 应用 | OAuth2.0 + PKCE | 安全处理客户端凭证,防止令牌泄露 |
| 快速原型 / 测试 | Basic Auth | 实现简单,无需额外库 |
| 服务间高安全通信 | mTLS + JWT | 双向证书认证 + 自包含令牌 |
架构建议:在生产环境中,通常不会只使用单一鉴权模式。推荐采用“组合策略”——对外暴露 OAuth2.0,内部服务间使用 JWT,监控和运维接口使用 API Key。中间件应支持多模式共存,根据请求路径或来源动态选择验证方式。
3.5 安全风险与防范措施
- 令牌泄露:所有模式都面临令牌被截获的风险。必须使用 HTTPS,并设置合理的过期时间。
- 重放攻击:JWT 和 API Key 可能被重放。建议引入
jti(JWT ID)或 nonce 机制,配合服务端缓存实现一次性使用。 - CSRF 攻击:Bearer Token 存储在 Cookie 中时易受 CSRF 攻击。建议将 Token 放在请求头中,或使用 SameSite Cookie 属性。
- 令牌撤销:JWT 一旦签发,在过期前无法撤销(除非维护黑名单)。OAuth2.0 的授权服务器可以主动撤销令牌,更适合需要动态权限管理的场景。
中间件实现要点:
- 所有鉴权中间件必须优先验证 HTTPS,拒绝非加密请求
- JWT 验证时,必须校验
exp、nbf、iss等标准声明 - API Key 应支持前缀识别(如
sk_live_xxx),便于区分环境 - OAuth2.0 中间件需实现令牌内省(Introspection)端点,用于验证不透明令牌