Oauth2是描述無狀態授權的協議(授權框架),因為是無狀態,所以我們不需要維護客戶端和服務器之間的會話。
Oauth2的工作原理:
此協議允許第三方客戶端代表資源所有者訪問受保護資源,Oauth2有四個基本角色:
資源所有者-就是資源的所有者 resource owner
資源服務器-托管所有受保護資源的服務器
客戶端-訪問資源服務器的應用程序
授權服務器-處理客戶端發出訪問令牌的服務器,這可以是與資源服務器相同的服務器
此外,有兩種類型的令牌:
訪問令牌(accessToken),通常具有有限的生命周期,並允許客戶端聽過在請求標頭中包含此令牌來訪問受保護資源
刷新令牌(refreshToken),刷新具有更長的生命周期的令牌,用於在新的訪問令牌到期后獲取新訪問令牌(無需再次向服務器發送憑據)
一般的訪問令牌和刷新令牌周期設置為多久才更合適呢?
阿里巴巴速賣通授權產生的Token,AccessToken有效期時間是10個小時,RefreshToken有效時間是半年;QQ的AccessToken有效期時間是30天,因為AccessToken的有效期時間比較長,所以並沒有RefreshToken的說法;微信的AccessToken是2個小時,RefreshToken是30天;新浪的AccessToken的有效期是7天;一般accessToken設置短一點一到兩個小時,accessToken時間太長一旦accessToken泄露就會
RefreshToken可以設置長一點。
客戶端需要在服務器上注冊才能接受客戶端ID(clientId)和客戶端秘鑰(clientSercet),這些客戶端id和客戶端秘鑰稍后在請求訪問令牌時使用。每個令牌具有由用戶在於授權服務器通信時定義的范圍(例如,用戶授權客戶端應用訪問資源服務器上的某些資源)。
Oauth2定義了4種不同的授權類型。這些授權類型定義客戶端和身份驗證/資源服務器的交互。
授權碼模式-機密客戶端基於重定向的流程,客戶端通過用戶代碼(web瀏覽器等)與服務器進行通信,典型的web服務器。
隱式類型(簡化模式)-不通過第三方應用程序的服務器,直接在瀏覽器上向認證服務器申請令牌,跳過了“授權碼”這個步驟,所有步驟在瀏覽器中完成,令牌對訪問者可見,且客戶端不需要認證。
資源所有者密碼憑證(密碼模式)-與受信任的客戶端一起使用,用戶憑證將傳給客戶端,然后傳給認證服務器並交換訪問和刷新令牌。
客戶端憑證-在客戶端本身是資源所有者(一個客戶端不與多個用戶一起運行)時使用,客戶端憑證直接交換給令牌。
運行流程:摘自RFC 6749
(A):用戶打開客戶端之后,客戶端要求用戶給予授權
(B):用戶同意給予客戶端授權
(C):客戶端使用(B)步驟獲得的授權,像認證服務器申請令牌
(D):認證服務器對客戶端進行認證以后,確認無誤,同意發放令牌(accessToken)。
(E):客戶端使用(D)步驟獲得的accessToken,向資源服務器申請獲取資源。
(F):資源服務器確定令牌無誤之后,同意向客戶端開放保護資源。
B步驟中,用戶怎么給予客戶端授權呢??
只有客戶端獲得授權,才能向認證服務器去申請訪問令牌。從而根據這個令牌去向資源服務器去請求獲得資源。
客戶端的授權模式有四種,就是上面說的四種模式,這邊主要對這四種模式進行詳細講解。
1、授權碼模式:通過客戶端的后台服務器與認證服務器進行交互。流程如下:
(A):用戶訪問客戶端,客戶端將用戶導向認證服務器,也就是引導直接去訪問認證服務器
(B):然后用戶選擇是否給予客戶端授權
(C):假如用戶給予授權,認證服務器則將用戶導向客戶端實現指定的“重定向URI”(redirection URI),同時附上一個授權碼。
(D):當客戶端收到這個授權碼之后,附上早先的“重定向URI”,直接去訪問認服務器向認證服務器去申請accessToken(令牌)。
(E):認證服務器確認了Authorization Code(授權碼)和Redirection URI(重定向URI)無誤之后,向客戶端返回訪問令牌(accessToken)和刷新令牌(refreshToken);
A步驟中,客戶端申請授權碼的URI中需要一些參數:
response_type:標識授權類型,必選項,此處的值固定為“code”
clientId:客戶端ID,必選項
redirect_uri:標識重定向URI,此處為可選項
scope:表示申請的權限范圍,可選項
state:表示客戶端當前的狀態,可以指定任意值,認證服務器會原封不動的返回這個值。
C步驟中,認證服務器回應給客戶端的URI,必須包括以下的參數。
code:表示授權碼,必選項。該碼的有效期應該會很短,通常設為10分鍾,客戶端只能用這個授權碼一次,否則會被授權服務器拒絕。該碼與客戶端ID和重定向URI是一一對應的關系。
state:如果客戶端的請求中包含這個參數,認證服務器返回的應該是這個一模一樣的參數。
D步驟中,客戶端根據授權碼去向認證服務器申請accessToken(令牌)的請求,包含以下幾個參數:
grant_type:表示使用的是授權模式,必選項,此處的值固定為“authorization_code”,
code:表示用於再給客戶端授權的時候獲得的授權碼,也就是C步驟中獲得的授權碼。
redirect_uri:表示重定向uri,必選項,且必須為A步驟中參數的值保持一致。
clientId:表示客戶端ID,表示的是必選項。
E步驟中,認證服務器對授權碼和重定向URI進行認證之后,返回的Http恢復包括以下的參數:
accessToken:表示授權令牌,必選項。
token_type:表示令牌類型,該值的大小寫不敏感,可以為bearer類型或者是mac類型
expires_in:表示過期時間,單位為秒,如果省略這個參數,必須使用其他的方式設置過期時間。
refreshToken:表示更新令牌,作用是為了下一次獲取訪問令牌,也就是accessToken。可選項,有的也沒有設置,但是盡量設置。
scope:表示權限范圍,如果與客戶端申請授權碼的一致,那么這一步可以省略。
其實我們可以采用postMan去獲得accessToken如下,這是使用postMan去獲得accessToken的參數:
下圖則是獲得的accessToken:
2、簡化模式或者隱式模式(implicit grant type):不通過第三方應用程序的服務器,直接在瀏覽器中向認證服務器申請令牌,跳過了“獲得授權碼”這個步驟。所有的步驟在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不需要認證。
(A):跟之前的一樣,客戶端將用戶導向認證服務器
(B):用戶決定是否給予客戶端授權
(C):假設用戶給予授權,認證服務器將用戶導向客戶端指定的“重定向URI”,並在URI的Hash部分包含了訪問令牌(accessToken)
(D):瀏覽器向資源服務器發出請求,其中不包括上一步收到的Hash值
(E):資源服務器返回一個網頁,其中包含的代碼可以獲得hash值中的令牌。
(F):瀏覽器執行上一步獲得的腳本,提取出令牌
(G):瀏覽器將accessToken(訪問令牌)發給客戶端
3、密碼模式:用戶向客戶端提供自己的用戶名和密碼,客戶端使用這些信息向服務提供商索要授權。
(A):用戶向客戶端提供用戶名和密碼。
(B):客戶端向認證服務器請求訪問令牌(accessToken)
(C):認證服務器確認無誤之后,向客戶端提供accessToken(訪問令牌)
4、客戶端模式:指客戶端以自己的名義,而不是以用戶的名義,向服務器提供商進行認證,嚴格的說客戶端模式並不屬於oauth框架索要解決的問題,在這種模式中,用戶直接向客戶端注冊,客戶端以自己的名義要求服務器提供商提供服務,其實不存在授權問題。
(A):客戶端直接向認證服務器去進行身份認證,並要求一個訪問令牌
(B):認證服務器進行認證之后,向客戶端返回一個accessToken。