OAuth2是一個授權(Authorization)協議。我們要和Spring Security的認證(Authentication)區別開來,認證(Authentication)證明的你是不是這個人,而授權(Authorization)則是證明這個人有沒有訪問這個資源(Resource)的權限。
下面這張圖來源於OAuth 2.0 authorization framework RFC Document,是OAuth2的一個抽象流程。
+--------+ +---------------+ | |--(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 ---| | +--------+ +---------------+
先來解釋一下上圖的名詞:
Resource Owner:資源所有者,即用戶
Client:客戶端應用程序(Application)
Authorization Server:授權服務器
Resource Server:資源服務器
再來解釋一下上圖的大致流程:
(A) 用戶連接客戶端應用程序以后,客戶端應用程序要求用戶給予授權
(B) 用戶同意給予客戶端應用程序授權
(C) 客戶端應用程序使用上一步獲得的授權(Grant),向授權服務器申請令牌
(D) 授權服務器對客戶端應用程序的授權(Grant)進行驗證后,確認無誤,發放令牌
(E) 客戶端應用程序使用令牌,向資源服務器申請獲取資源
(F) 資源服務器確認令牌無誤,同意向客戶端應用程序開放資源
從上面的流程可以看出,如何獲取授權(Grant)才是關鍵。在OAuth2中有4種授權類型:
1. Authorization Code(授權碼模式):功能最完整、流程最嚴密的授權模式。通過第三方應用程序服務器與認證服務器進行互動。廣泛用於各種第三方認證。
2. Implicit(簡化模式):不通過第三方應用程序服務器,直接在瀏覽器中向認證服務器申請令牌,更加適用於移動端的App及沒有服務器端的第三方單頁面應用。
3. Resource Owner Password(密碼模式):用戶向客戶端服務器提供自己的用戶名和密碼,用戶對客戶端高度信任的情況下使用,比如公司、組織的內部系統,SSO。
4. Client Credentials(客戶端模式):客戶端服務器以自己的名義,而不是以用戶的名義,向認證服務器進行認證。
下面主要講最常用的(1)和(3)。此外,還有一個模式叫Refresh Token,也會在下面介紹。
Authorization Code(授權碼模式)
+----------+ | Resource | | Owner | | | +----------+ ^ | (B) +----|-----+ Client Identifier +---------------+ | -+----(A)-- & Redirection URI ---->| | | User- | | Authorization | | Agent -+----(B)-- User authenticates --->| Server | | | | | | -+----(C)-- Authorization Code ---<| | +-|----|---+ +---------------+ | | ^ v (A) (C) | | | | | | ^ v | | +---------+ | | | |>---(D)-- Authorization Code ---------' | | Client | & Redirection URI | | | | | |<---(E)----- Access Token -------------------' +---------+ (w/ Optional Refresh Token) Note: The lines illustrating steps (A), (B), and (C) are broken into two parts as they pass through the user-agent.
它的步驟如下:
(A) 用戶(Resource Owner)通過用戶代理(User-Agent)訪問客戶端(Client),客戶端索要授權,並將用戶導向認證服務器(Authorization Server)。
(B) 用戶選擇是否給予客戶端授權。
(C) 假設用戶給予授權,認證服務器將用戶導向客戶端事先指定的"重定向URI"(redirection URI),同時附上一個授權碼。
(D) 客戶端收到授權碼,附上早先的"重定向URI",向認證服務器申請令牌。這一步是在客戶端的后台的服務器上完成的,對用戶不可見。
(E) 認證服務器核對了授權碼和重定向URI,確認無誤后,向客戶端發送訪問令牌(access token)和更新令牌(refresh token)。這一步也對用戶不可見。
Resource Owner Password(密碼模式)
+----------+ | Resource | | Owner | | | +----------+ v | Resource Owner (A) Password Credentials | v +---------+ +---------------+ | |>--(B)---- Resource Owner ------->| | | | Password Credentials | Authorization | | Client | | Server | | |<--(C)---- Access Token ---------<| | | | (w/ Optional Refresh Token) | | +---------+ +---------------+ Figure 5: Resource Owner Password Credentials Flow
它的步驟如下:
(A) 用戶(Resource Owner)向客戶端(Client)提供用戶名和密碼。
(B) 客戶端將用戶名和密碼發給認證服務器(Authorization Server),向后者請求令牌。
(C) 認證服務器確認無誤后,向客戶端提供訪問令牌。
令牌刷新(refresh token)
+--------+ +---------------+ | |--(A)------- Authorization Grant --------->| | | | | | | |<-(B)----------- Access Token -------------| | | | & Refresh Token | | | | | | | | +----------+ | | | |--(C)---- Access Token ---->| | | | | | | | | | | |<-(D)- Protected Resource --| Resource | | Authorization | | Client | | Server | | Server | | |--(E)---- Access Token ---->| | | | | | | | | | | |<-(F)- Invalid Token Error -| | | | | | +----------+ | | | | | | | |--(G)----------- Refresh Token ----------->| | | | | | | |<-(H)----------- Access Token -------------| | +--------+ & Optional Refresh Token +---------------+
具體流程不再分析,我們已知,當我們申請token后,Authorization Server不僅給了我們Access Token,還有Refresh Token。當Access Token過期后,我們用Refresh Token訪問/refresh端點就可以拿到新的Access Token了。
本節只講概念,在接下來的幾節中會搭建一組含有Client Application, Authorization Server, Resource Server的微服務群,並使用Eureka和Config組件管理。