OAuth 2.0規范於2012年發布,很多大型互聯網公司(比如:微信、微博、支付寶)對外提供的SDK中,授權部分基本上都是按這個規范來實現的。
OAuth 2.0提供了4種基本的標准授權流程,最為復雜的是Code(授權碼)這種類型,流程圖如下:(摘自RFC6749官方文檔)
上圖中有幾個術語解釋一下:
Resource: 受保護的資源,比如:用戶abc在微信上的用戶資料(頭像,朋友圈之類)
Resource Owner:資源所有人,即:上面講的用戶abc
Client:指第三方應用,比如:微信
Authorization Server:授權服務器,可以理解成微信對外開放的SDK授權API
User-Agent: 用戶代理,在一般的互聯網應用中,這個通常就是指瀏覽器
其實這張圖中,還隱藏了一個身份:Resource Server資源服務器,即真正提供資源訪問接口的服務
整個流程如下:
A: 瀏覽器(User-Agent)請求第三方應用比如微信(Client)上的資源,這時候還沒有access_token,所以微信會請求重定向到認證服務器(Authorization Server)
B: 認證服務器這時會呈現出一個授權界面(即:我們經常在手機遇到的微信授權認證界面,告訴用戶XXX應用正在請求您在微信上的資料,然后下面有一個"同意授權"的按鈕)
C: 用戶同意授權后,認證服務器會返回瀏覽器一個code(本文稱為授權碼),通俗的理解,相當於瀏覽器這時候取了一個號(就象我們去銀行辦業務,大堂經理先給你一個排隊號,這個號碼並非敏感信息,被其它人知道了, 一般問題也不大),瀏覽器拿着這個號再去請求微信上的資源
D:再次被重定向到認證服務器,用code來換真正的訪問令牌(access_token) (有點類似於銀行排到你的號了,你拿這個號去X號櫃台真正辦理業務,這時人家會讓你出示身份證,卡號等敏感信息,只不過在oAuth 2中,這些敏感信息是動態生成,有時效限制的),最終瀏覽器拿到了access_token
E: 有了access_token,瀏覽器訪問微信上受保護的資源時,資源服務器校驗access_token的合法性后,返回用戶想要的資源。
注:上面提到的銀行取號辦理業務,這個示例可能有點牽強,大家主要記住[授權->拿Code->用Code換Access_Token->帶着Access_Token訪問資源]這一套流程。
下面這張圖可能更容易理解一些:
除了授權碼這種常用流程外,還有一種用戶名、密碼的流程也被廣泛使用,序列圖如下:
password模式與code模式最大的不同,在於沒有code換access_token這一步。另外:由於access_token的有效期比較短,為了避免頻繁按上述流程重新獲取新access_token,oAuth還有一個refresh_token的概念,通常refresh_token過期時間比較長(比如:一周甚至更長),當發現access_token快過期時,可以主動用refresh_token去獲取一個新的access_token,序列圖如下:
流程搞清楚了,最后談談實現,spring-security有一個oAuth2的"插件",可以直接在spring-security的基礎上支持oAuth2.0,項目地址:https://github.com/spring-projects/spring-security-oauth,項目的/samples/oauth2/下有二個示例,對應oAuth server與oAuth client端,有興趣的可以研究下。
此外,oschina還有二個國人提供的優秀示例,我已經搬到github上了,地址:
https://github.com/yjmyzz/spring-oauth-server
https://github.com/yjmyzz/spring-oauth-client
不過關於spring-security-oauth2有幾點要注意一下:
a)默認access_token的時間非常長,大約是12小時,建議調小
b)在access_token未過期時,多次請求將返回同一個access_token
c)在code模式下,client_secrect在第二步code換access_token時,才需要,第一步申請code不需要
參考文章: