1. 介紹
OAUTH協(xié)議為用戶資源的授權提供了一個安全的、開放而又簡易的標準迂卢。與以往的授權方式不同之處是OAUTH的授權不會使第三方觸及到用戶的帳號信息(如用戶名與密碼)楣富,即第三方無需使用用戶的用戶名與密碼就可以申請獲得該用戶資源的授權奕谭,因此OAUTH是安全的。oAuth是Open Authorization的簡寫尝蠕。
2. 理解
OAuth 就是一種授權機制。數(shù)據(jù)的所有者告訴系統(tǒng)载庭,同意授權第三方應用進入系統(tǒng)看彼,獲取這些數(shù)據(jù)。系統(tǒng)從而產(chǎn)生一個短期的進入令牌(token)囚聚,用來代替密碼靖榕,供第三方應用使用。
3. 角色
- OAuth定義了四種角色:
- 資源所有者
能夠許可受保護資源訪問權限的實體靡挥。當資源所有者是個人時序矩,它作為最終用戶被提及。 - 資源服務器
托管受保護資源的服務器跋破,能夠接收和響應使用訪問令牌對受保護資源的請求簸淀。 - 客戶端
使用資源所有者的授權代表資源所有者發(fā)起對受保護資源的請求的應用程序瓶蝴。術語“客戶端”并非特指任何特定的的實現(xiàn)特點(例如:應用程序是否在服務器、臺式機或其他設備上執(zhí)行)租幕。 - 授權服務器
在成功驗證資源所有者且獲得授權后頒發(fā)訪問令牌給客戶端的服務器舷手。
授權服務器和資源服務器之間的交互超出了本規(guī)范的范圍。授權服務器可以和資源服務器是同一臺服務器劲绪,也可以是分離的個體男窟。一個授權服務器可以頒發(fā)被多個資源服務器接受的訪問令牌。
- 資源所有者
4. 協(xié)議流程
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
上圖中所示的抽象OAuth 2.0流程描述了四個角色之間的交互贾富,包括以下步驟:
- (A)客戶端向從資源所有者請求授權歉眷。授權請求可以直接向資源所有者發(fā)起(如圖所示),或者更可取的是通過作為中介的授權服務器間接發(fā)起颤枪。
- (B)客戶端收到授權許可汗捡,這是一個代表資源所有者的授權的憑據(jù),使用本規(guī)范中定義的四種許可類型之一或 者使用擴展許可類型表示畏纲。授權許可類型取決于客戶端請求授權所使用的方式以及授權服務器支持的類型扇住。
- (C)客戶端與授權服務器進行身份認證并出示授權許可請求訪問令牌。
- (D)授權服務器驗證客戶端身份并驗證授權許可盗胀,若有效則頒發(fā)訪問令牌艘蹋。
- (E)客戶端從資源服務器請求受保護資源并出示訪問令牌進行身份驗證。
- (F)資源服務器驗證訪問令牌票灰,若有效則滿足該請求女阀。
客戶端用于從資源所有者獲得授權許可(步驟(A)和(B)所示)的更好方法是使用授權服務器作為中介。
5. 授權方式
OAuth 2.0 規(guī)定了四種獲得令牌的流程屑迂。你可以選擇最適合自己的那一種强品,向第三方應用頒發(fā)令牌。
- 授權碼
- 隱式授權
- 資源所有者密碼憑據(jù)
- 客戶端憑據(jù)
6. 詳細介紹四種授權方式
授權碼(authorization code):指的是第三方應用先申請一個授權碼屈糊,然后再用該碼獲取令牌的榛。
這種方式是最常用的流程,安全性也最高逻锐,它適用于那些有后端的 Web 應用夫晌。授權碼通過前端傳送,令牌則是儲存在后端昧诱,而且所有與資源服務器的通信都在后端完成晓淀。這樣的前后端分離,可以避免令牌泄漏盏档。第一步凶掰,A 網(wǎng)站提供一個鏈接,用戶點擊后就會跳轉到 B 網(wǎng)站,授權用戶數(shù)據(jù)給 A 網(wǎng)站使用懦窘。下面就是 A 網(wǎng)站跳轉 B 網(wǎng)站的一個示意鏈接前翎。
https://b.com/oauth/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read
上面 URL 中,response_type參數(shù)表示要求返回授權碼(code)畅涂,client_id參數(shù)讓 B 知道是誰在請求港华,redirect_uri參數(shù)是 B 接受或拒絕請求后的跳轉網(wǎng)址,scope參數(shù)表示要求的授權范圍(這里是只讀)午衰。
- 第二步立宜,用戶跳轉后,B 網(wǎng)站會要求用戶登錄臊岸,然后詢問是否同意給予 A 網(wǎng)站授權橙数。用戶表示同意,這時 B 網(wǎng)站就會跳回redirect_uri參數(shù)指定的網(wǎng)址帅戒。跳轉時商模,會傳回一個授權碼,就像下面這樣蜘澜。
https://a.com/callback?code=AUTHORIZATION_CODE
上面 URL 中,code參數(shù)就是授權碼响疚。
- 第三步鄙信,A 網(wǎng)站拿到授權碼以后,就可以在后端忿晕,向 B 網(wǎng)站請求令牌装诡。
https://b.com/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL
上面 URL 中,client_id參數(shù)和client_secret參數(shù)用來讓 B 確認 A 的身份(client_secret參數(shù)是保密的践盼,因此只能在后端發(fā)請求)鸦采,grant_type參數(shù)的值是AUTHORIZATION_CODE,表示采用的授權方式是授權碼咕幻,code參數(shù)是上一步拿到的授權碼渔伯,redirect_uri參數(shù)是令牌頒發(fā)后的回調網(wǎng)址。
- 第四步肄程,B 網(wǎng)站收到請求以后锣吼,就會頒發(fā)令牌。具體做法是向redirect_uri指定的網(wǎng)址蓝厌,發(fā)送一段 JSON 數(shù)據(jù)玄叠。
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101,
"info":{...}
}
上面 JSON 數(shù)據(jù)中,access_token字段就是令牌拓提,A 網(wǎng)站在后端拿到了读恃。
隱式授權:有些 Web 應用是純前端應用,沒有后端。這時就不能用上面的方式了寺惫,必須將令牌儲存在前端疹吃。RFC 6749 就規(guī)定了第二種方式,允許直接向前端頒發(fā)令牌肌蜻。這種方式?jīng)]有授權碼這個中間步驟互墓,所以稱為(授權碼)"隱藏式"(implicit)。
第一步蒋搜,A 網(wǎng)站提供一個鏈接篡撵,要求用戶跳轉到 B 網(wǎng)站,授權用戶數(shù)據(jù)給 A 網(wǎng)站使用豆挽。
https://b.com/oauth/authorize?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read
上面 URL 中育谬,response_type參數(shù)為token,表示要求直接返回令牌帮哈。
- 第二步膛檀,用戶跳轉到 B 網(wǎng)站,登錄后同意給予 A 網(wǎng)站授權娘侍。這時咖刃,B 網(wǎng)站就會跳回redirect_uri參數(shù)指定的跳轉網(wǎng)址,并且把令牌作為 URL 參數(shù)憾筏,傳給 A 網(wǎng)站嚎杨。
https://a.com/callback#token=ACCESS_TOKEN
上面 URL 中,token參數(shù)就是令牌氧腰,A 網(wǎng)站因此直接在前端拿到令牌枫浙。
注意,令牌的位置是 URL 錨點(fragment)古拴,而不是查詢字符串(querystring)箩帚,這是因為 OAuth 2.0 允許跳轉網(wǎng)址是 HTTP 協(xié)議,因此存在"中間人攻擊"的風險黄痪,而瀏覽器跳轉時紧帕,錨點不會發(fā)到服務器,就減少了泄漏令牌的風險桅打。
這種方式把令牌直接傳給前端焕参,是很不安全的。因此油额,只能用于一些安全要求不高的場景叠纷,并且令牌的有效期必須非常短,通常就是會話期間(session)有效潦嘶,瀏覽器關掉涩嚣,令牌就失效了崇众。資源所有者密碼憑據(jù):如果你高度信任某個應用,RFC 6749 也允許用戶把用戶名和密碼航厚,直接告訴該應用顷歌。該應用就使用你的密碼,申請令牌幔睬,這種方式稱為"密碼式"(password)眯漩。
第一步,A 網(wǎng)站要求用戶提供 B 網(wǎng)站的用戶名和密碼麻顶。拿到以后赦抖,A 就直接向 B 請求令牌。
https://oauth.b.com/token?
grant_type=password&
username=USERNAME&
password=PASSWORD&
client_id=CLIENT_ID
上面 URL 中辅肾,grant_type參數(shù)是授權方式队萤,這里的password表示"密碼式",username和password是 B 的用戶名和密碼矫钓。
第二步要尔,B 網(wǎng)站驗證身份通過后,直接給出令牌新娜。注意赵辕,這時不需要跳轉,而是把令牌放在 JSON 數(shù)據(jù)里面概龄,作為 HTTP 回應还惠,A 因此拿到令牌。
這種方式需要用戶給出自己的用戶名/密碼旁钧,顯然風險很大,因此只適用于其他授權方式都無法采用的情況互拾,而且必須是用戶高度信任的應用歪今。憑證式:(client credentials),適用于沒有前端的命令行應用颜矿,即在命令行下請求令牌寄猩。
第一步,A 應用在命令行向 B 發(fā)出請求骑疆。
https://oauth.b.com/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
上面 URL 中田篇,grant_type參數(shù)等于client_credentials表示采用憑證式,client_id和client_secret用來讓 B 確認 A 的身份箍铭。
- 第二步泊柬,B 網(wǎng)站驗證通過以后,直接返回令牌诈火。
這種方式給出的令牌兽赁,是針對第三方應用的,而不是針對用戶的,即有可能多個用戶共享同一個令牌刀崖。
7.令牌的使用
A 網(wǎng)站拿到令牌以后惊科,就可以向 B 網(wǎng)站的 API 請求數(shù)據(jù)了。
此時亮钦,每個發(fā)到 API 的請求馆截,都必須帶有令牌。具體做法是在請求的頭信息蜂莉,加上一個Authorization
字段蜡娶,令牌就放在這個字段里面。
curl -H "Authorization: Bearer ACCESS_TOKEN" \
"https://api.b.com"
上面命令中巡语,ACCESS_TOKEN
就是拿到的令牌翎蹈。
8. 更新令牌
令牌的有效期到了,如果讓用戶重新走一遍上面的流程男公,再申請一個新的令牌荤堪,很可能體驗不好,而且也沒有必要枢赔。OAuth 2.0 允許用戶自動更新令牌澄阳。
具體方法是,B 網(wǎng)站頒發(fā)令牌的時候踏拜,一次性頒發(fā)兩個令牌碎赢,一個用于獲取數(shù)據(jù),另一個用于獲取新的令牌(refresh token 字段)。令牌到期前技潘,用戶使用 refresh token 發(fā)一個請求几蜻,去更新令牌。
https://b.com/oauth/token?
grant_type=refresh_token&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
refresh_token=REFRESH_TOKEN
上面 URL 中枕赵,grant_type
參數(shù)為refresh_token
表示要求更新令牌,client_id
參數(shù)和client_secret
參數(shù)用于確認身份位隶,refresh_token
參數(shù)就是用于更新令牌的令牌拷窜。
B 網(wǎng)站驗證通過以后,就會頒發(fā)新的令牌涧黄。
9. 實戰(zhàn)
如何通過 OAuth 獲取 API 數(shù)據(jù)篮昧。
很多網(wǎng)站登錄時,允許使用第三方網(wǎng)站的身份笋妥,這稱為"第三方登錄"懊昨。
GitHub 為例,寫一個最簡單的應用春宣,演示第三方登錄疚颊。
-
第三方登錄的原理
所謂第三方登錄狈孔,實質就是 OAuth 授權。用戶想要登錄 A 網(wǎng)站材义,A 網(wǎng)站讓用戶提供第三方網(wǎng)站的數(shù)據(jù)均抽,證明自己的身份。獲取第三方網(wǎng)站的身份數(shù)據(jù)其掂,就需要 OAuth 授權油挥。
舉例來說,A 網(wǎng)站允許 GitHub 登錄款熬,背后就是下面的流程深寥。- A 網(wǎng)站讓用戶跳轉到 GitHub。
- GitHub 要求用戶登錄贤牛,然后詢問"A 網(wǎng)站要求獲得 xx 權限惋鹅,你是否同意?"
- 用戶同意殉簸,GitHub 就會重定向回 A 網(wǎng)站闰集,同時發(fā)回一個授權碼。
- A 網(wǎng)站使用授權碼般卑,向 GitHub 請求令牌武鲁。
- GitHub 返回令牌.
- A 網(wǎng)站使用令牌,向 GitHub 請求用戶數(shù)據(jù)蝠检。
-
應用登記
- 進入GitHub官網(wǎng)沐鼠,登錄。
- 打開 Setting > Developer setting > OAuth applications
- 點擊 Register a new application
- 填入基本的app信息
-
提交表單以后叹谁,GitHub 應該會返回客戶端 ID(client ID)和客戶端密鑰(client secret)饲梭,這就是應用的身份識別碼。
示例倉庫
阮一峰示例倉庫