出自筆者站點文章: 利用Spring Boot Oauth2 來熟悉oauth2 之 - Authorization Code Grant
參考文獻
- rfc 文檔: RFC 6749 - The OAuth 2.0 Authorization Framework
- Spring boot oauth2 示例 Tutorial · Spring Boot and OAuth2
代碼:
https://github.com/spring-guides/tut-spring-boot-oauth2
流程圖
從RFC文檔複製過來的流程圖, 來輔助我們理解oauth2 的Authorization Code Grant
探究竟
clone代碼,將maven的工程(tut-spring-boot-oauth2\simple)導入eclipse跑起來。
You can also run all the apps on the command line using
mvn spring-boot:run
or by building the jar file and running it with mvn package andjava -jar target/*.jar
代碼就一個文件,簡單如下:
@SpringBootApplication
@EnableOAuth2Sso
public class SocialApplication {
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
}
接力於Spring Boot的Auto Configuration 的功能,我們不需要做任何的配置。
由於引入了spring-boot-starter-security
默認情況下,所有的請求都需求登錄。
Chrome打開http://localhost:8080, 並打開開發者工具,選中’Preserve log’; 瀏覽器將自動重定向到/login; 由於oauth2 client的引入,請求又再次被重定向至facebook進行授權;開始了授權的流程。
在chrome的開發者工具中Network 標籤, 按住CTRL/CMD 選中Doc和Other可以過濾掉大部分靜態資源請求,方便我們來分析整個流程
角色解釋
官方解釋請參考:Oauth2 Roles
在我們這個示例中:
- Resource Owner: 人,也就是這個facebook 賬號的所有人
- User Agent: 這裏就是Chrome 瀏覽器
- Client:代表Owner去請求被保戶的資源的應用(這裏就是Spring Boot的Web App)
- Resource Server: Facebook 授權能訪問的資源服務(這裏拿到access token後獲取了用戶的信息,沒有訪問其他的Resource Server)
- Authorization Server: 集中授權服務器,負責驗證access token
流程分解
1. 請求資源服務首頁:http://localhost:8080/ Response 302 :
...
Location:http://localhost:8080/login
...
Set-Cookie:JSESSIONID=8C24D287C93ECDE88C3D4BD7410668FB;path=/;HttpOnly
...
2. 跳轉至登錄頁面:http://localhost:8080/login
Request Headers: SESSIONID=8C24D287C93ECDE88C3D4BD7410668FB
Reponse Headers: Location:https://www.facebook.com/dialog/oauth?client_id=233668646673605&redirect_uri=http://localhost:8080/login&response_type=code&state=undAFm
3. 頁面將跳轉至facebook,開始Authorization Code Grant的流程, 對應流程圖中的步驟(A)
https://www.facebook.com/dialog/oauth?client_id=233668646673605&redirect_uri=http://localhost:8080/login&response_type=code&state=undAFm
請求的URL參數包括了用戶的標識,本地生成的state以及授權成功後返回到資源服務的地址。response_type=code 標識了授權的類型是“Authorization Code Grant”
The client includes its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted (or denied).
Facebook未檢測到任何用戶登錄信息,重定向至facebook的登錄頁面。
4. 請求登錄頁面
5. 輸入賬號信息後,點擊登錄後的post 請求
登錄成功後,重定向至facebook的oauth頁面進行流程的(B)步驟
6. 登錄成功後,進入oauth頁面進入流程的(B)
截圖是第二次嘗試,由於第一次的時候用戶針對當前client已經授權訪問基本信息後。 在第二次登錄後,授權的頁面就不會出現, 而是直接重定向到被授權client的redirect_uri。流程中的(C) 也就同B一起在沒有和用戶交互的情況下完成了。
C步驟中,服務器迴應客戶端的URI,包含以下參數:
code:表示授權碼,必選項。該碼的有效期應該很短,通常設爲10分鐘,客戶端只能使用該碼一次,否則會被授權服務器拒絕。該碼與客戶端ID和重定向URI,是一一對應關係。
state:如果客戶端的請求中包含這個參數,認證服務器的迴應也必須一模一樣包含這個參數。
7. 拿着facebook授權的code進行資源服務的login請求
/login?code=** Spring Boot Oauth2 拿到對應的code後,1)去facebook請求獲取access token; 2)獲取到對應的token信息後既可以通過token進一步獲取用戶相關信息(這兩步的api 請求是在服務器端進行),進而完成Spring Boot的Authentication
, 成功後重定向到請求1(第一步);同時創建了新的session。
從上面的步驟及截圖的status code可以看出來整個oauth2的流程基本是在重定向中完成。3,4,5,6 分別與資源服務無關 (即:Spring Boot Web 應用無關)。
Spring是如何將authentication 導向/代理給 oauth2 client的?這些都在引入的依賴幫我們自動實現了。