1. OAuth2.0 基础:核心概念、授权码模式与令牌生命周期
1.1 OAuth2.0 协议核心概念
OAuth2.0 是一种授权框架,允许第三方应用在用户授权的前提下,有限度地访问用户在资源服务器上存储的资源,而无需暴露用户的长期凭证(如密码)。该协议定义了四个核心角色:
| 角色 | 英文名称 | 职责描述 |
|---|---|---|
| 资源所有者 | Resource Owner | 拥有受保护资源的实体,通常是最终用户。决定是否授权第三方应用访问其资源。 |
| 客户端 | Client | 请求访问受保护资源的第三方应用(如 Web 后端、移动 App、单页应用)。 |
| 授权服务器 | Authorization Server | 验证资源所有者身份并颁发令牌的服务器。通常与资源服务器分离部署。 |
| 资源服务器 | Resource Server | 托管受保护资源的服务器,通过验证令牌的有效性来决定是否允许客户端访问。 |
关键原则:OAuth2.0 的核心是令牌(Token)而非凭证。令牌是一个不透明的字符串,代表授权决策的结果,客户端只需持有令牌即可访问资源,无需知晓用户密码。
1.2 授权码模式(Authorization Code Grant)流程
授权码模式是 OAuth2.0 中最完整、最安全的授权流程,适用于有后端服务器的机密客户端。该模式通过引入一个临时的“授权码”作为中间凭证,避免了令牌直接暴露在用户代理(浏览器)中。
完整流程包含以下步骤:
- 客户端发起授权请求:客户端将用户重定向到授权服务器的授权端点,请求中包含
client_id、redirect_uri、response_type=code以及可选的scope。 - 用户认证并授权:授权服务器验证用户身份(通常通过登录页面),并向用户展示客户端请求的权限范围。用户确认授权。
- 颁发授权码:授权服务器将用户重定向回客户端指定的
redirect_uri,并在 URL 查询参数中附加一个临时的code(授权码)。 - 客户端换取令牌:客户端使用授权码,通过后端通道(服务器到服务器)向授权服务器的令牌端点发起 POST 请求,携带
client_id、client_secret、code、redirect_uri以及grant_type=authorization_code。 - 颁发访问令牌:授权服务器验证授权码和客户端凭证后,返回
access_token(访问令牌)和可选的refresh_token(刷新令牌)。 - 访问受保护资源:客户端使用
access_token向资源服务器请求资源,资源服务器验证令牌后返回数据。
安全优势:授权码模式的关键在于,令牌是通过安全的服务器间通信(步骤 4-5)颁发的,而不是通过用户浏览器重定向。这有效防止了令牌在 URL 或浏览器历史中被泄露。
1.3 令牌类型与生命周期
OAuth2.0 协议定义了两种核心令牌类型,它们在用途、生命周期和安全策略上存在显著差异:
| 属性 | 访问令牌(Access Token) | 刷新令牌(Refresh Token) |
|---|---|---|
| 用途 | 用于访问受保护资源,是资源服务器验证客户端权限的直接凭证。 | 用于在访问令牌过期后,向授权服务器申请新的访问令牌,无需用户重新授权。 |
| 生命周期 | 短生命周期,通常为 15 分钟到 1 小时(由授权服务器配置)。 | 长生命周期,通常为数天到数月,甚至可持久化存储。 |
| 安全风险 | 泄露后攻击者可在有效期内访问资源,但影响范围受限于令牌权限和短有效期。 | 泄露后攻击者可无限期刷新令牌,风险极高,需严格保护。 |
| 存储要求 | 客户端内存或短期缓存,无需持久化。 | 必须安全持久化存储(如加密数据库),且支持吊销机制。 |
| 传输方式 | 通常放在 HTTP 请求的 Authorization: Bearer 头中。 |
仅在客户端与授权服务器之间的安全后端通道中传输。 |
安全警示:刷新令牌是 OAuth2.0 安全体系中的“万能钥匙”。一旦泄露,攻击者可以持续获取新的访问令牌。在生产环境中,必须对刷新令牌实施轮换策略(Refresh Token Rotation)——每次使用刷新令牌获取新访问令牌时,同时颁发一个新的刷新令牌并使旧的失效。
1.4 令牌生命周期管理策略
在实际的分布式系统中,令牌的生命周期管理直接影响系统的安全性和用户体验。以下是常见的生命周期管理策略:
- 短生命周期 + 自动刷新:访问令牌设置较短有效期(如 15 分钟),客户端在令牌过期前通过刷新令牌自动获取新令牌。这种方式在安全性和用户体验之间取得了良好平衡。
- 令牌缓存:在客户端(如 Go 中间件)中缓存访问令牌,避免每次请求都向授权服务器验证。缓存需考虑并发安全,防止多个协程同时刷新令牌导致授权服务器压力过大。
- 令牌吊销:授权服务器应提供令牌吊销端点,允许在用户主动登出或检测到安全事件时立即使令牌失效。
- 令牌内省(Introspection):资源服务器可以通过调用授权服务器的内省端点来验证令牌的当前状态(是否有效、是否被吊销)。
1.5 令牌格式:不透明令牌 vs JWT
在实际实现中,访问令牌可以采用两种主流格式:
| 特性 | 不透明令牌(Opaque Token) | JWT(JSON Web Token) |
|---|---|---|
| 格式 | 随机字符串,无内部结构 | 三段式 Base64 编码(Header.Payload.Signature) |
| 自包含性 | 否,资源服务器需调用授权服务器内省端点验证 | 是,令牌自身包含用户信息、权限、过期时间等声明 |
| 验证性能 | 依赖网络调用,延迟较高 | 本地验证签名即可,无需网络调用,性能高 |
| 吊销处理 | 简单,授权服务器维护黑名单即可 | 复杂,需维护令牌黑名单或缩短有效期 |
| 常见场景 | 高安全要求、需要实时吊销的场景 | 分布式系统、微服务架构、需要减少网络调用的场景 |