最近工做中遇到了多系統間的受權登陸,對OAuth2.0進行了學習研究,並總結備忘。sql
咱們登陸一些論壇等網站的時候,若是不想單獨註冊該網站帳號,能夠選擇用微信或QQ帳號進行受權登陸。 這樣的第三方登陸方式究竟是怎麼實現的呢?難道是騰訊把咱們微信或QQ帳號信息賣給了這些網站?很顯然,騰訊是不會這麼幹的,這種登陸方式的實現,其實就是使用的OAuth2.0的受權登陸方式。 json
相似地,在公司內部,若是公司有多套不一樣的軟件系統,例如公司內網的財務報銷系統、考勤系統、報銷系統、人事系統等,也能夠實現一個員工帳號就能受權訪問全部系統,而不須要每一個系統都開通單獨的帳號,設置獨立的密碼。這是一般所說的SSO單點登陸,而OAuth2.0是單點登陸的實現方式之一。 後端
OAuth2.0是一種容許第三方應用程序使用資源全部者的憑據得到對資源有限訪問權限的一種受權協議。瀏覽器
例如在上述例子中,經過微信登陸論壇的過程,就至關於微信容許該論壇做爲第三方應用程序在通過微信用戶受權後,經過微信頒發的受權憑證有限地訪問用戶的微信頭像、手機號,性別等受限制的資源,從而來構建自身的登陸邏輯。安全
注:在OAuth2.0協議中,第三方應用程序獲取的憑證並不等同於資源擁有者持有的用戶名和密碼,以上面例子來講,微信是不會直接將用戶的用戶名、密碼等信息做爲憑證返回給該論壇的。這種受權訪問憑證通常來講就是一個表示特定範圍、生存週期和其訪問權限的一個由字符串組成的訪問令牌,也就是咱們常說的token。在這種模式下OAuth2.0協議中經過引入一個受權層來將第三方應用程序與資源擁有者進行分離,而這個受權層也就是常說的「auth認證服務/sso單點登陸服務器」。 服務器
在OAuth2.0協議中定義瞭如下四個角色: 微信
1)resource owner(資源擁有者)app
即可以有權授予對保護資源訪問權限的實體。例如咱們使用經過微信帳號登陸論壇,而微信帳號信息的實際擁有者就是微信用戶,也被稱爲最終用戶。 學習
2)resource server(資源服務器)網站
承載受保護資源的服務器,可以接收使用訪問令牌對受保護資源的請求並響應,它與受權服務器能夠是同一服務器(下述的「簡化模式」),也能夠是不一樣服務器(下述的「受權碼模式」)。在上述例子中該角色就是微信服務器。
3)client(客戶端)
表明資源全部者及其受權發出對受保護資源請求的應用程序。在上面的例子中的用戶要註冊的論壇就是該角色。
4)authorization server(受權服務器)
認證服務器,即服務提供商專門用來處理認證受權的服務器。例如微信開放平臺提供的認證服務的服務器。
仍是以微信受權登陸舉例,流程以下:
流程說明:
在上述流程中比較關鍵的動做是resource owner(資源擁有者,用戶)怎麼樣才能給Client(豆瓣網論壇)受權,由於只有有了這個受權,Client角色才能夠獲取訪問令牌(access_token),進而經過令牌訪問其餘資源接口。而關於客戶端如何得到受權的問題,在OAuth2.0中定義了四種受權方式,目前微信受權登陸,使用的就是其中最經常使用的一種:「受權碼模式」(authorization_code)。
OAuth2.0定義了四種受權模式,它們分別是:
四種模式對比說明:
1.受權碼模式(authorization code)
功能最完整、流程最嚴密的受權模式,安全性最高,也最爲經常使用。
特色是經過客戶端的後臺服務器,與「服務提供商」的認證服務進行互動(如微信開放平臺),如上述微信帳號登陸豆瓣網的流程就是受權碼模式的實現。
這種模式下受權代碼並非客戶端直接從資源全部者獲取,而是經過受權服務器(authorization server)做爲中介來獲取,受權認證的過程也是資源全部者直接經過受權服務器進行身份認證,避免了資源全部者身份憑證與客戶端共享的可能,所以是十分安全的。
2.簡化模式(implicit grant type)
簡化模式是對受權碼模式的簡化,用於在瀏覽器中使用腳本語言如JS實現的客戶端中,特色是不經過客戶端應用程序的服務器,而是直接在瀏覽器中向認證服務器申請令牌,跳過了「受權碼臨時憑證」這個步驟。其全部的步驟都在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不須要認證。若是使用此種受權方式來實現微信登陸豆瓣網論壇的過程流程示例以下:
能夠看出,與受權碼模式的不一樣之處在於:在第4步用戶完成受權後,認證服務器是直接返回了access_token令牌至用戶瀏覽器端,而並無先返回臨時受權碼code,而後由客戶端的後端服務去經過受權碼再去獲取access_token令牌,從而省去了一個跳轉步驟,提升了交互效率。
可是因爲這種方式訪問令牌access_token會在URL片斷中進行傳輸,所以可能會致使訪問令牌被其餘未經受權的第三方截取,因此安全性上並非那麼的強壯。
3.密碼模式(resource owner password credentials)
在密碼模式中,用戶須要向客戶端提供本身的用戶名和密碼,客戶端使用這些信息向「服務提供商」索要受權。這至關於在豆瓣網中使用微信登陸,咱們須要在豆瓣網輸入微信的用戶名和密碼,而後由豆瓣網使用咱們的微信用戶名和密碼去向微信服務器獲取受權信息。
這種模式通常用在用戶對客戶端高度信任的狀況下,由於雖然協議規定客戶端不得存儲用戶密碼,可是實際上這一點並非特別好強制約束。就像在豆瓣網輸入了微信的用戶名和密碼,豆瓣網存儲不存儲咱們並非很清楚,因此安全性是很是低的。所以通常狀況下是不會考慮使用這種模式進行受權的。公司內網之間相互信任的子系統間也許纔有可能使用。
若是使用此種受權方式來實現微信登陸豆瓣網論壇的過程流程示例以下:
4.客戶端模式(client credentials)
客戶端模式是指客戶端以本身的名義,而不是以用戶的名義,向「服務提供方」進行認證。嚴格地說,客戶端模式並不屬於OAuth2.0協議所要解決的問題。在這種模式下,用戶並不須要對客戶端受權,用戶直接向客戶端註冊,客戶端以本身的名義要求「服務提供商」提供服務,其實不存在受權問題。
步驟以下:
(1)客戶端向認證服務器進行身份認證,並要求一個access_token令牌。
(2)認證服務器確認無誤後,向客戶端提供訪問access_token令牌。
(3)客戶端後續攜帶access_token令牌繼續後續業務請求流程。
步驟(1)中,客戶端發出的HTTP請求,包含如下參數:
示例: POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=client_credentials
認證服務器必須以某種方式,驗證客戶端身份。而後在步驟(2)中,認證服務器向客戶端提供訪問access_token令牌,下面是一個例子。
示例: HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA", "iss":"簽發受權者",
"sub":"服務使用者",
"aud":"服務提供者",
"exp":"過時時間", "iat":"簽發時間", "other_custom_parameter":"value" }
綜上所述,雖然在OAuth2.0協議中定義了四種客戶端受權認證模式,可是實際上大部分實際應用場景中使用的都是受權碼(authorization code)的模式,如微信開放平臺、微博開放平臺等使用的基本都是受權碼認證模式。
若是用戶訪問的時候,客戶端的"訪問令牌"已通過期,則須要使用"更新令牌"申請一個新的訪問令牌。
客戶端發出更新令牌的HTTP請求,包含如下參數:
示例: POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA