OAuth 2.0 是業界標準的授權框架,允許第三方應用在用戶授權下訪問受保護資源,而無需獲取用戶憑證。本文從協議流程、核心術語、Java 手動實現三個維度深度講解。
| 角色 | 說明 |
|---|---|
| Resource Owner (用戶) | 擁有受保護資源的實體 |
| Client (客戶端/第三方應用) | 請求訪問資源的應用 |
| Authorization Server (授權服務器) | 驗證用戶並頒發 Access Token |
| Resource Server (資源服務器) | 存儲受保護資源,驗證 Token |
關鍵參數:client_id、client_secret、redirect_uri、scope、state(防 CSRF)、code(授權碼)、access_token、refresh_token。
+----------+ +---------------+
| User | | Auth Server |
+----------+ +---------------+
| |
| 1. 點擊「授權登錄」 |
|------------------------------------------>|
| |
| 2. 重定向到授權頁面 |
|<------------------------------------------|
| |
| 3. 用戶登錄並授權 |
|------------------------------------------>|
| |
| 4. 重定向回 Client 帶 code |
|<------------------------------------------|
| |
| 5. Client 用 code 換 access_token |
|------------------------------------------>|
| |
| 6. 返回 access_token (+ refresh_token) |
|<------------------------------------------|
| |
| 7. 攜帶 token 訪問資源 |
|------------------------------------------>|
構建基礎字符串,HMAC-SHA1 簽名:
String baseString = "GET&" + urlEncode(authUrl) + "&" + urlEncode(params);
// 簽名密鑰 = consumer_secret + "&" + token_secret (若有)
String signature = hmacSha1(baseString, signingKey);
String authUrl = "https://provider.com/oauth/authorize?" +
"client_id=" + clientId +
"&redirect_uri=" + urlEncode(redirectUri) +
"&response_type=code" +
"&scope=read_write" +
"&state=" + randomState; // 必須驗證回調時的 state
HttpRequest.post(tokenUrl)
.form("grant_type=authorization_code")
.form("code=" + authCode)
.form("redirect_uri=" + redirectUri)
.form("client_id=" + clientId)
.form("client_secret=" + clientSecret)
.execute()
.body(); // 解析 JSON 獲取 access_token, expires_in, refresh_token
HttpRequest.get(resourceUrl)
.header("Authorization", "Bearer " + accessToken)
.execute();
// 刷新
POST /oauth/token
grant_type=refresh_token
&refresh_token=xxx
&client_id=xxx
&client_secret=xxx
// 撤銷 (RFC 7009)
POST /oauth/revoke
token=xxx
&token_type_hint=access_token
&client_id=xxx
&client_secret=xxx