OAuth 2.0 定义了 4 种授权模式(Grant Type),用于不同场景下的令牌获取。以下是每种模式的详细说明、适用场景和对比:
一、授权码模式(Authorization Code Grant)
适用场景
• Web 应用(有后端服务器)
• 移动端应用(需安全存储 client_secret
)
• 最安全的模式,推荐公开客户端使用
流程
特点
• 令牌不暴露给浏览器(通过后端交换)
• 支持 refresh_token
• 需预注册 redirect_uri
防止钓鱼攻击
二、隐式模式(Implicit Grant)
适用场景
• 单页应用(SPA) 或纯前端应用
• 无后端服务器的场景
• 已被 OAuth 2.1 废弃(建议用授权码模式 + PKCE 替代)
流程
特点
• 直接返回 access_token
(无中间授权码)
• 令牌通过 URL 片段传递(前端可见,存在泄露风险)
• 不支持 refresh_token
三、密码模式(Resource Owner Password Credentials Grant)
适用场景
• 受信任的客户端(如公司内部系统)
• 用户需直接在客户端输入用户名/密码
• 高风险,仅限无法使用其他模式的场景
流程
特点
• 用户需向客户端暴露密码(违反最小权限原则)
• 仅适用于高信任度环境(如内部系统)
• 支持 refresh_token
四、客户端凭证模式(Client Credentials Grant)
适用场景
• 服务器到服务器的通信(无用户参与)
• 机器对机器(M2M)认证
• 访问与用户无关的公共资源
流程
特点
• 无用户参与
• 令牌权限范围由客户端注册时决定
• 不支持 refresh_token
五、模式对比与选型指南
模式 | 安全性 | 适用客户端类型 | 是否需要用户参与 | 令牌存储位置 |
---|---|---|---|---|
授权码模式 | ⭐⭐⭐⭐⭐ | Web 应用、移动端(有后端) | 是 | 后端安全存储 |
隐式模式 | ⭐⭐ | SPA(已过时) | 是 | 前端存储(高风险) |
密码模式 | ⭐ | 受信任的内部系统 | 是 | 后端存储 |
客户端凭证模式 | ⭐⭐⭐⭐ | 服务器到服务器 | 否 | 后端安全存储 |
六、最佳实践
- 优先使用授权码模式(尤其是公开客户端)
- 避免隐式模式(OAuth 2.1 已废弃,改用 PKCE 增强的授权码模式)
- 密码模式仅限高信任环境(如公司内部工具)
- 客户端凭证模式用于 M2M 场景(如定时任务、API 网关)
- 强制 HTTPS 防止令牌泄露
七、Spring Security 中实现示例
授权码模式配置(Google 登录):
# application.yml
spring:
security:
oauth2:
client:
registration:
google:
client-id: your-client-id
client-secret: your-client-secret
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
客户端凭证模式配置:
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2ClientCredentialsGrantRequestEntityConverter converter =
new OAuth2ClientCredentialsGrantRequestEntityConverter();
DefaultClientCredentialsTokenResponseClient client =
new DefaultClientCredentialsTokenResponseClient();
client.setRequestEntityConverter(converter);
AuthorizedClientServiceOAuth2AuthorizedClientManager manager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
manager.setAuthorizedClientProvider(
new ClientCredentialsOAuth2AuthorizedClientProvider());
return manager;
}
通过理解这四种授权模式,您可以根据具体场景选择最合适的认证流程,平衡安全性与用户体验。