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-idclient-secret: your-client-secretauthorization-grant-type: authorization_coderedirect-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;
}
通過理解這四種授權模式,您可以根據具體場景選擇最合適的認證流程,平衡安全性與用戶體驗。