理解oauth

oauth 的誕生爲了解決什麼問題?

1,爲了自己的用戶不流失,在安全的情況下接入第三方服務。

2,爲了解決第三方服務使用服務商資源的時候保證儘可能安全。

oauth的角色及其關係

oauth中有3個角色,用戶,服務商,第三方服務。用戶於服務商之間存在完全信任關係,用戶把所有信息都放在服務商那裏。第三方服務給用戶提供服務需要用戶的一些信息。

oauth本質

oauth的策略本質即是爲第三方服務下發用戶令牌,第三方服務通過令牌可以拿到用戶的部分可讀信息。由此可以將服務商的身份用在多個網站處。對這個本質提出幾個問題:

1,令牌是什麼?令牌是一個身份的象徵,古時候,皇帝亮出自己的令牌,小老百姓就紛紛下跪,不然就要殺頭,不光皇帝,其他任何人拿着皇帝的令牌亮出都一樣。皇帝只有一個,這個令牌標識了皇帝,必須是唯一的。那麼oauth中令牌也需要符合上述條件,唯一性。由此想到uuid等唯一的標識。可以作爲唯一標識下發給第三方,第三方拿到了標識以後,就可以用標識來服務商這裏取數據了。

2,爲什麼要下發一個令牌,用戶換取用戶身份?首先,用戶對第三方服務不完全信任,不希望自己的賬戶密碼被第三方服務知道。當然如果希望,服務商也不提供這樣的服務,因爲服務商承諾用戶的賬戶密碼不可能給別人,如果給了,服務商來一個服務你給別人賬戶密碼,生意還做不做。萬一第三方服務泄露,你也就泄露了。因此就算用戶鼓勵服務商提供賬戶密碼,服務商也不能。因此下發令牌就是oauth的原則。

oauth流程

基於本質設計基本流程:用戶訪問第三服務時,第三方服務需要身份,就去服務商那裏取身份,服務商下發一個令牌給第三方。

問題1,下發誰的令牌?類似我們登錄王者榮耀時,王者榮耀要拿身份直接把微信拉起來,進入微信點擊。同時也可以跳到qq登錄頁輸入賬戶密碼或者直接選擇已經在線的賬戶登錄。也就是在第三放去服務商那裏的時候,第三方服務是需要知道是要誰的身份,那麼這個時候需要用戶點擊或者輸入用戶名密碼,這個動作輸入用戶名密碼不是第三方服務的,而是服務商的頁面,也就是登錄服務商。(手機上微信處於登錄狀態,那麼直接把手機上的身份發給服務端,服務端就直接下發令牌給第三方即可。)

爲解決上述問題,流程需要添加用戶確認身份動作:用戶訪問第三服務時,第三方服務需要身份,就去服務商那裏取身份,服務商確認用戶身份,然後下發一個令牌給第三方。

問題2,令牌下發給第三方,那麼第三方如果令牌泄漏了,那麼任何人都可以拿着令牌來取用戶的身份,雖然沒有賬號密碼權限大,但是令牌可訪問的數據也就泄露了。因此對令牌需要設計一個過期時間,令牌過期以後就不可用了,重新下發。過期時間多長呢?據說一線大廠都是2小時。(具體看場景吧)但是在這2個小時內,同樣泄露了有着嚴重的後果。因此對此,需要第三方也要在服務商裏面獲取一個賬戶密碼,由此來確認第三方服務的身份,那麼第三方服務在服務商中就表現爲一個應用。如果沒有用戶身份,只拿個令牌,也不認。

上述過程通過設置應用的身份和用戶的身份來限制,但是如果兩個數據泄露仍然存在安全的問題。進行以下分析

1,首先我們考慮第三方數據庫泄露,因此我們設置令牌有效期爲2小時,按理這種事發生概率很小。因爲註冊的第三方應用也需要被服務商授權,具備一定的信任。

2,網絡傳輸中的令牌泄露。網絡傳輸僅僅在於客戶端到服務端網絡傳輸中存在網絡安全問題。以上oauth流程中,服務商向用戶確認身份後,服務商即可發送令牌給第三方。如果直接發送給第三方服務端,服務端到服務端基本不存在安全問題。但是這個時候用戶客戶端還停留在服務商的登錄成功頁面,如果給出重定向往回跳轉,客戶端也不具備標識知道這是哪個客戶端登錄的,爲了解決這個問題,這個令牌需要下發客戶端重定向訪問第三方應用服務端的時候標識人的身份。

至此,oauth1.0的基本雛形出現了,oauth1.0的實現方案即與以上推導結果一致。

oauth1.0流程

1,第三方請求request token, 作爲第三方應用的身份標識。

2,帶着request token向服務商請求用戶身份,服務商確認用戶。

3,用戶確認完畢帶着用戶token(令牌)重定向到callback地址,這個callback是第三方提供的一個服務。

oauth1.0中對callbackurl沒有強制要求,如果不填則返回一個靜態頁面,用戶去複製這個access token請求服務端。就有人說了用戶自己複製,這是玩蛇嗎?可是我印象裏在唸書那會手機端上有自動複製粘貼驗證碼幫助自動登錄的功能。如上oauth1.0存在安全問題:

1,攻擊者可以把callback寫成自己的,然後請求過去誘導用戶授權,用戶一旦授權,攻擊者就可以拿着令牌去請求用戶身份了。

2,如果說不適用callbackurl方式,oauth1.0支持這種給一個靜態地址裏面寫入令牌,只要搶在用戶授權後訪問前去訪問這個網址就能拿到用戶令牌。

我覺得其實只要在服務商處對callback進行一個校驗,也就是限定域名,那就不會存在第一種安全問題了。但爲解決安全問題,oauth提出oauth1.0a做出修補。

oauth1.0a對oauth1.0的改進

在oauth1.0的基礎上作出了改進:

1,oauth1.0a中在請求request token時就需要填入callbackurl,這裏的signature是加入了callbackurl的簽名,這樣攻擊者沒辦法猜到加入callbackurl以後的簽名的,因此oauth1.0用戶沒法使用自己的callbackurl的。

2,oauth1.0a 不支持靜態頁面授權。通過callbackurl拿到的也再試一個令牌,而是一個授權碼,這個授權碼再去獲取用戶身份令牌。也就是這個令牌已經不被客戶端知道了。這裏的授權碼

綜合以上的情況,終於是實現了安全的開放授權協議。

oauth 2.0

由於oauth 1.0 方面比較單一,僅僅能用於web應用,且其授權過程較爲複雜。針對這些,oauth2.0去掉了複雜的簽名部分,並且提供了4中授權流程,不再只支持單一的授權。

爲滿足各中需求,針對有服務端的第三方服務,提供的是:Authorization Code,這種方法最貼近oauth1.0a,採用授權碼來獲取access token。

1,第三方請求服務商,需要指定response_type 爲code,即返回一個授權碼

2,服務商得到user的同意,把code 打給redirect_uri

3,第三方拿到授權碼,服務端拿着自己已知的sercet 和 code 去獲取令牌。這裏返回兩個令牌,一個短期有效,另一個長期有效,可以多次通過長期token獲取短期token。

這裏針對沒有服務端的第三方服務(也可以叫第三方應用),他就把服務商當着服務端,但是服務端需要確認他的身份,就必須走個授權,這種方式叫:Implicit Grant

1,第三方應用請求服務端,指定response_type 爲 token,那麼就不返回授權碼,而是返回一個token。

2,服務商得到用戶的同意以後,把token打給客戶端。

3,這個token通過redirect_uri 打到客戶端,客戶端拿到以後token即可使用。

針對可信的應用,拿着用戶的用戶名密碼來請求資源,oauth2.0也提供這樣的服務:Resource Owner Password Credentials

1,第三方服務帶着用戶名和密碼來服務端請求grant_type = password,返回要給token給他就完事了。

還有最後一種,只是帶着應用身份哪一個應用身份的憑證來,不驗證用戶身份的方式。叫做:Client Credentials

1,帶着應用的id和sercet來請求access token,返回一個給他就完了。

這樣拿到的token只能訪問與用戶無關的數據,或者進行與用戶無關的操作。

討論 (這部分隨時添加)

1,refresh token的作用,oauth官方文檔說,refresh token的獲取只與授權服務器交互,通過refresh可以獲取access token,引入refresh token的好處有兩個,一個是access token可能會被存在端上,同時會頻繁的與資源服務器之間交互,容易被泄露出去。因此access token有過期時間,比較短,保證安全。access token過期,就使用refresh token去刷新,這個refresh token放在服務端,只與授權服務器之間交互,所以可以設置較長時間,access token與資源服務器交互,可以獲取資源,過期時間較短。


侵刪,參考
https://blog.huoding.com/2011/11/08/126

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章