OAuth2.0授權登錄
最近工作中遇到了多系統間的授權登錄,對OAuth2.0進行了學習研究,並總結備忘。
【場景】
我們登錄一些論壇等網站的時候,如果不想單獨注冊該網站賬號,可以選擇用微信或QQ賬號進行授權登錄。 這樣的第三方登錄方式到底是怎么實現的呢?難道是騰訊把我們微信或QQ賬號信息賣給了這些網站?很顯然,騰訊是不會這么干的,這種登錄方式的實現,其實就是使用的OAuth2.0的授權登錄方式。
類似地,在公司內部,如果公司有多套不同的軟件系統,例如公司內網的財務報銷系統、考勤系統、報銷系統、人事系統等,也可以實現一個員工賬號就能授權訪問所有系統,而不需要每個系統都開通單獨的賬號,設置獨立的密碼。這是通常所說的SSO單點登錄,而OAuth2.0是單點登錄的實現方式之一。
【定義】
OAuth2.0是一種允許第三方應用程序使用資源所有者的憑據獲得對資源有限訪問權限的一種授權協議。
例如在上述例子中,通過微信登錄論壇的過程,就相當於微信允許該論壇作為第三方應用程序在經過微信用戶授權后,通過微信頒發的授權憑證有限地訪問用戶的微信頭像、手機號,性別等受限制的資源,從而來構建自身的登錄邏輯。
注:在OAuth2.0協議中,第三方應用程序獲取的憑證並不等同於資源擁有者持有的用戶名和密碼,以上面例子來說,微信是不會直接將用戶的用戶名、密碼等信息作為憑證返回給該論壇的。這種授權訪問憑證一般來說就是一個表示特定范圍、生存周期和其訪問權限的一個由字符串組成的訪問令牌,也就是我們常說的token。在這種模式下OAuth2.0協議中通過引入一個授權層來將第三方應用程序與資源擁有者進行分離,而這個授權層也就是常說的“auth認證服務/sso單點登錄服務器”。
在OAuth2.0協議中定義了以下四個角色:
1)resource owner(資源擁有者)
即能夠有權授予對保護資源訪問權限的實體。例如我們使用通過微信賬號登錄論壇,而微信賬號信息的實際擁有者就是微信用戶,也被稱為最終用戶。
2)resource server(資源服務器)
承載受保護資源的服務器,能夠接收使用訪問令牌對受保護資源的請求並響應,它與授權服務器可以是同一服務器(下述的“簡化模式”),也可以是不同服務器(下述的“授權碼模式”)。在上述例子中該角色就是微信服務器。
3)client(客戶端)
代表資源所有者及其授權發出對受保護資源請求的應用程序。在上面的例子中的用戶要注冊的論壇就是該角色。
4)authorization server(授權服務器)
認證服務器,即服務提供商專門用來處理認證授權的服務器。例如微信開放平台提供的認證服務的服務器。
【流程】
還是以微信授權登錄舉例,流程如下:
流程說明:
- 首先微信用戶點擊豆瓣網論壇的微信授權登錄按鈕后,豆瓣網論壇會將請求通過URL重定向的方式跳轉至微信用戶授權界面;
- 此時微信用戶實際上是在微信上進行身份認證,與豆瓣網論壇並無交互了,這一點非常類似於購物后,使用網銀支付的場景;
- 用戶使用微信客戶端掃描二維碼認證或者輸入用戶名密碼后,微信會驗證用戶身份信息的正確性,如正確,則認為用戶確認授權微信登錄豆瓣網論壇,此時會先生成一個臨時憑證,並攜帶此憑證通過用戶瀏覽器將請求重定向回豆瓣網在第一次重定向時攜帶的callBackUrl地址;
- 之后用戶瀏覽器會攜帶臨時憑證訪問豆瓣網服務,豆瓣網則通過此臨時憑證再次調用微信授權接口,獲取正式的訪問憑據access_token;
- 在豆瓣網獲取到微信授權訪問憑據access_token后,此時用戶的授權基本上就完成了,后續豆瓣網要做的只是通過此token再訪問微信提供的相關接口,獲取微信允許授權開發的用戶信息,如頭像,昵稱等,並據此完成自身的用戶邏輯及用戶登錄會話邏輯。
【模式】
在上述流程中比較關鍵的動作是resource owner(資源擁有者,用戶)怎么樣才能給Client(豆瓣網論壇)授權,因為只有有了這個授權,Client角色才可以獲取訪問令牌(access_token),進而通過令牌訪問其他資源接口。而關於客戶端如何獲得授權的問題,在OAuth2.0中定義了四種授權方式,目前微信授權登錄,使用的就是其中最常用的一種:“授權碼模式”(authorization_code)。
OAuth2.0定義了四種授權模式,它們分別是:
- 授權碼模式(authorization code)
- 簡化模式(implicit)
- 密碼模式(resource owner password credentials)
- 客戶端模式(client credentials)
四種模式對比說明:
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請求,包含以下參數:
- grant_type:表示授權類型,此處的值固定為"client_credentials",必選項。
- scope:表示權限范圍,可選項。
示例: 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請求,包含以下參數:
- grant_type:表示使用的授權模式,此處的值固定為"refresh_token",必選項。
- refresh_token:表示早前收到的更新令牌,必選項。
- scope:表示申請的授權范圍,不可以超出上一次申請的范圍,如果省略該參數,則表示與上一次一致。
示例: 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
來自:https://www.cnblogs.com/wwcom123/p/11600463.html