本系列文章
Spring Cloud :: Security :: Oauth2 – ⓪ OAuth2模型詳述
Spring Cloud :: Security :: Oauth2 – ① 待定
…寫在前面
文中很多專有名詞在初次使用時我會標註一下中文,但是在後面使用過程中我還是會使用英文來表示,因為所有的標準的出處都是英文,中文的翻譯並沒有標準,用英文會減少歧義通俗易懂。
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
背景
最近在做基於Spring Cloud的一系列架構,在認證、許可權這一塊準備採用OAuth2來做,Spring Cloud本身對於OAuth2的支援很不錯,這一塊叫做Spring Cloud Security
,預設就是使用OAuth2的模型來支援。本文把自己做架構過程中積累的技術以及插圖分享出來。
概述
介紹OAuth2模型
本文主要描述OAuth2的模型以及基本執行原理,內容略略抽象,盡最大限度用圖來描述,結合後續的基於Spring Cloud的程式碼和架構圖理解會更為便捷。
正文
OAuth2
我們經常所說的OAuth2,顧名思義,就是OAuth模型的第二版。此版本允許第三方應用獲取資源訪問許可權,並且在很多大型網際網路企業中進行使用。
基礎知識
Roles 角色
OAuth2定義的4個角色
- Resource Owner :資源擁有者,電腦前的你。
- Resource Server :資源伺服器,託管受保護的資料的伺服器。
- Client :客戶端,請求訪問資源伺服器的應用。可以是網站,可以是javascript指令碼,也可以是任何app等。
- Authorization Server :授權伺服器,向Client(客戶端)發放token(令牌)的伺服器,token用於Client請求Resource Server。
佛系圖解釋一下(來源於RFC6749)https://tools.ietf.org/html/r…
+--------+ +---------------+
| |--(A)------- Authorization Grant --------->| |
| | | |
| |<-(B)----------- Access Token -------------| |
| | | |
| | | |
| | +----------+ | |
| |--(C)---- Access Token ---->| | | |
| | | | | |
| |<-(D)- Protected Resource --| Resource | | Authorization |
| Client | | Server | | Server |
| | | | | |
| | | | | |
| | | | | |
| | +----------+ | |
| | | |
| | | |
| | | |
| | | |
+--------+ +---------------+
- (A):授權
- (B):獲得token
- (C):使用token訪問Resource Server
- (D):獲得受保護的資料
這張圖中沒有Resource Owner出現,我們姑且認為這個過程都是系統自動的,不需要人的參與。
Token 令牌
Token(令牌)是Authorization Server生成的一段類似於uuid的隨機字串,在Client請求的時候生成並返回。
令牌的型別
- Access Token : 訪問令牌。允許第三方應用程式使用並訪問使用者的資料。此token由Client作為引數或者請求header傳送到Resource Server,並且應具有有限的生命週期,過期時限由Authorization Server決定。
- Refresh Token : 重新整理令牌。與access token一併生成,但與access token不同的是,它不會在每一個向Resource Server請求資料的時候傳送給伺服器。僅僅用於伺服器過期時傳送給伺服器來更新access token。
Authorization grant types 授權型別
OAuth2定義了4種授權的型別,具體選用哪一種型別取決於不同的場景以及需求。
Authorization Code Grant 授予授權程式碼
何時使用
如果Client是Web伺服器,那麼預設應該使用這種模式,這也是OAuth2預設的方式。這種模式允許Client長期訪問Token,並且重新整理Token的續訂,即使用Refresh Token。
例如:
- Resource Owner : 你
- Resource Server: Google伺服器
- Client: Facebook網站
- Authorization Server:Google伺服器
場景
- 網站希望獲得你的Google個人資料的資訊。
- 你將被Client(網站)重定向到Authorization Server(Google)
- 如果你授權訪問,Authorization Server會在回撥中向Client傳送Authorization Code
- 使用Authorization Code向Authorization Server申請Access Token
- Client可以使用Access Token查詢Resource Server並獲取你的個人資料資訊。
佛系架構圖 參考(http://goo.gl/hbl1B)
題外話,http://www.websequencediagram… 真的很棒
『 Legend 』:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ >=========> : Http POST request. ┃
┃ <~~~~~~~~~< : Response from server. ┃
┃ >---------> : Forward or redirect to. ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
『 Sequence Diagram 』:
┏━━━━━━━━━━━━━━━┓ ┏━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓
┃Ressource Owner┃ ┃Client┃ ┃Authorization Server┃ ┃Resource Server ┃
┗━━━━━━━━━━━━━━━┛ ┗━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━┛
┃ ┃ ┃ ┃
┃ ┃ Authorization Code Request ┏━┓ ┃
┃ ┃ >===================================> ┃ ┃ ┃
┃ ┃ +----------------------------------+ ┃
┃ ┃ | Needs client_id,redirect_uri, | ┃
┃ | reponse_type=code[,scope,state] | ┃
┃ Login & Consent +----------------------------------+ ┃
┃ >===================================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ Authorization Code Reponse ┃ ┃ ┃
┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ ┗━┛ ┃
┃ ┃ ┃ ┃
┃ ┃ ┏━┓ ┃
┃ ┃ Exchange Code For Access Token ┃ ┃ ┃
┃ ┃ >===================================> ┃ ┃ ┃
┃ ┃ +--------------------------------------------+ ┃
┃ ┃ | Needs client_id,client_secret,redirect_uri | ┃
┃ ┃ | grant_type=authorization_code,code | ┃
┃ ┃ +--------------------------------------------+ ┃
┃ ┃ Access Token [+ Refresh Token] ┃ ┃ ┃
┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┗━┛ ┃
┃ ┃ ┃ ┃
┃ ┃ ┃ ┃
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃loop┃ ┃ ┃ ┃ ┃ ┃
┣━━━━╋ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ Call API with Access Token ┃ ┏━┓ ┃
┃ ┃ ┃ >===================================================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ Reponse with Data ┃ ┃ ┃
┃ ┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┃ ┃ ┃
┃ ┃ ┃ ┃ ┗━┛ ┃
┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┃ ┃ ┃ ┃
┃ ┃ ┃ ┃
┏━━━━━━━━━━━━━━━┓ ┏━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓
┃Ressource Owner┃ ┃Client┃ ┃Authorization Server┃ ┃Resource Server ┃
┗━━━━━━━━━━━━━━━┛ ┗━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━┛
Implicit Grant 隱性授權
何時使用
與Authorization Code Grant的方式不同的是,Client不是一個Web Server,而是嵌入在瀏覽器的指令碼語言,比如javascript。
例如:
- Resource Owner: 你
- Resource Server: Google伺服器
- Client: 使用Jquery或Angular js的客戶端
- Authorization Server: Google伺服器
場景:
- Client的js端希望獲得Google的個人資料資訊
- 你會被重定向到Google的Authorization Server
- 如果你授權使用自己的Google個人資訊資料給Client,則Authorization Server會把Access Token非同步回撥給js的Client
- Client可以使用Access Token查詢Resource Server並獲取你的個人資料資訊(通過js的非同步呼叫)。
佛系架構圖
『 Legend 』:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ >=========> : Http POST request. ┃
┃ <~~~~~~~~~< : Response from server. ┃
┃ >---------> : Forward or redirect to. ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
『 Sequence Diagram 』:
┏━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓
┃Ressource Owner┃ ┃Client(Javascript App)┃ ┃Authorization Server┃ ┃Resource Server ┃
┗━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━┛
┃ ┃ ┃ ┃
┃ ┃ Authorization Token Request ┏━┓ ┃
┃ ┃ >===================================> ┃ ┃ ┃
┃ ┃ +----------------------------------+ ┃
┃ ┃ | Needs client_id,redirect_uri, | ┃
┃ | reponse_type=token[,scope,state] | ┃
┃ Login & Consent +----------------------------------+ ┃
┃ >===================================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ Access Token ┃ ┃ ┃
┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ ┗━┛ ┃
┃ ┃ ┃ ┃
┃ ┃ ┏━┓ ┃
┃ ┃ Access Token Info Request ┃ ┃ ┃
┃ ┃ >===================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ Access Token Info ┃ ┃ ┃
┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┗━┛ ┃
┃ ┃ ┃ ┃
┃ ┃ ┃ ┃
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃loop┃ ┃ ┃ ┃ ┃ ┃
┣━━━━╋ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ Call API with Access Token ┃ ┏━┓ ┃
┃ ┃ ┃ >===================================================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ +-----------------------------+ ┃
┃ ┃ ┃ ┃ | Implement CORS For Cross | ┃
┃ ┃ ┃ ┃ | Domain Requests | ┃
┃ ┃ ┃ ┃ +-----------------------------+ ┃
┃ ┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ Reponse with Data ┃ ┃ ┃
┃ ┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┃ ┃ ┃
┃ ┃ ┃ ┃ ┗━┛ ┃
┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┃ ┃ ┃ ┃
┃ ┃ ┃ ┃
┏━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓
┃Ressource Owner┃ ┃Client(Javascript App)┃ ┃Authorization Server┃ ┃Resource Server ┃
┗━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━┛
Resource Owner Password Credentials 授予資源擁有者密碼憑證
何時使用
利用這種方式,你的憑證,一般來講就是密碼,會先傳送給Client,然後通過Client傳送給Authorization Server。通過這種方式可以看出,Client與Authorization Server之間應該有著絕對的信任,一般情況下,Client與Authorization Server是同等許可權體系的,換句話說,應該是client.example.com與auth.example.com相同網站的不同resource級別的關係,由於使用者的密碼都是屬於example.com體系下的,所以在client.example.com或者任何xxx.example.com中輸入密碼,去resource.example.com獲取資料都是可以接受的。
例如:
- Resource Owner: 你
- Resource Server:resource.example.com伺服器
- Client: new.example.com的伺服器,需要呼叫自己網站的認證系統
- Authorization Server: auth.example.com伺服器
場景:
- example公司開發了新的new.example.com的子系統
- 呼叫自己公司的auth.example.com認證
- 認證成功後從Authorization Server獲取Access Token
- 利用Access Token去呼叫自己的resource.example.com的api獲取相應資料
佛系架構圖
『 Legend 』:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ >=========> : Http POST request. ┃
┃ <~~~~~~~~~< : Response from server. ┃
┃ >---------> : Forward or redirect to. ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
『 Sequence Diagram 』:
┏━━━━━━━━━━━━━━━┓ ┏━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓
┃Ressource Owner┃ ┃Client ┃ ┃Authorization Server┃ ┃Resource Server ┃
┗━━━━━━━━━━━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━┛
┃ Authorization ┃ ┃ ┃
┃>================>┃ ┃ ┃
┃ with Credentials ┃ ┃ ┃
┃ ┃ Access Token Request ┏━┓ ┃
┃ ┃ >===================================> ┃ ┃ ┃
┃ ┃ +-------------------------------------+ ┃
┃ ┃ | Needs client_id,redirect_uri, | ┃
┃ | reponse_type=password[,scope,state] | ┃
┃ Login & Consent +-------------------------------------+ ┃
┃ >======================================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ Access Token ┃ ┃ ┃
┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ ┗━┛ ┃
┃ ┃ ┃ ┃
┃ ┃ ┏━┓ ┃
┃ ┃ Access Token Info Request ┃ ┃ ┃
┃ ┃ >===================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ Access Token Info ┃ ┃ ┃
┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┗━┛ ┃
┃ ┃ ┃ ┃
┃ ┃ ┃ ┃
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃loop┃ ┃ ┃ ┃ ┃ ┃
┣━━━━╋ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ Call API with Access Token ┃ ┏━┓ ┃
┃ ┃ ┃ >===================================================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ Reponse with Data ┃ ┃ ┃
┃ ┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┃ ┃ ┃
┃ ┃ ┃ ┃ ┗━┛ ┃
┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┃ ┃ ┃ ┃
┏━━━━━━━━━━━━━━━┓ ┏━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓
┃Ressource Owner┃ ┃Client ┃ ┃Authorization Server┃ ┃Resource Server ┃
┗━━━━━━━━━━━━━━━┛ ┗━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━┛
Client Credentials Grant 授權客戶憑證
何時使用
當Client自身是Resource Owner的場合,這時只需要認證client_id即可,本身不產生其他的授權認證。
例如:
- Resource Owner: 任何一家網站
- Resource Server:Google伺服器
- Client: =Resource Owner
- Authorization Server: Google伺服器
場景:
- 網站A儲存自己的所有files在Google的雲端儲存伺服器
- 網站A需要通過Google Api進行files的操作,操作前必須在Authorization Server中認證
- 一旦認證成功,網站A獲取Access Token來訪問Google的Resource Server
- Authorization Server不會授權其他的許可權給Resource Owner
佛系架構圖
『 Legend 』:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ >=========> : Http POST request. ┃
┃ <~~~~~~~~~< : Response from server. ┃
┃ >---------> : Forward or redirect to. ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
『 Sequence Diagram 』:
┏━━━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓
┃Client(Resource Owner)┃ ┃Authorization Server┃ ┃Resource Server ┃
┗━━━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━┛
┃ ┃ ┃
┃ ┃ ┃
┃ ┃ ┃
┃ Access Token Request ┏━┓ ┃
┃>=======================================================> ┃ ┃ ┃
┃ +-----------------------------------------------+ ┃
┃ | Needs client_id,redirect_uri, | ┃
┃ | reponse_type=client_credentials[,scope,state] | ┃
┃ +-----------------------------------------------+ ┃
┃ ┃ ┃ ┃
┃ ┃ ┃ ┃
┃ ┃ ┃ ┃
┃ Access Token ┃ ┃ ┃
┃<~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┃ ┃ ┃
┃ ┗━┛ ┃
┃ ┃ ┃
┃ ┃ ┃
┃ ┃ ┃
┏━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃loop┃ ┃ ┃ ┃ ┃
┣━━━━╋ ┃ ┃ ┃ ┃
┃ ┃ Call API with Access Token ┃ ┏━┓ ┃
┃ ┃ >=====================================================================================> ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ Reponse with Data ┃ ┃ ┃
┃ ┃ <~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< ┃ ┃ ┃
┃ ┃ ┃ ┗━┛ ┃
┃ ┃ ┃ ┃ ┃
┃ ┃ ┃ ┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
┃ ┃ ┃
┏━━━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓
┃Client(Resource Owner)┃ ┃Authorization Server┃ ┃Resource Server ┃
┗━━━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━┛