理解OAuth 2.0授權


一、什么是OAuth 

二、什么場景下會用到OAuth授權

三、OAuth 2.0中的4個成員

四、OAuth 2.0授權流程

五、OAuth 2.0授權模式

1、    authorization code(授權碼模式)

2、    implicit(簡化模式)

3、    resource owner password credentials(密碼模式)

4、    client credentials(客戶端模式)

六、小結

 

一、什么是OAuth

  所謂的OAuth(Open Authorization)本質上就是一張開放的協議,OAuth協議為用戶資源的授權提供了一個安全的、開放而又簡易的標准。 與以往的授權方式不同該授權不會使第三方觸及到用戶的賬戶信息,即第三方無需使用用戶名密碼就可以申請該用戶資源的授權,因此OAuth是安全的。這是來自百度百科對OAuth的解釋。

  而OAuth2.0呢,故名思義就是OAuth的下一個版本,同時它也是授權領域的行業標准協議,OAuth2.0不支持向后兼容,即不支持OAuth1.0,徹底廢止了OAuth1.0協議,OAuth2.0致力於使客戶端開發者通過更簡單的流程為Web應用、桌面應用以及手機客戶端等設備進行授權。2012年10月,OAuth2.0協議正式發布為RFC6749。目前各大開放平台,如騰訊、新浪、百度等等也都是以OAuth2.0協議作為支撐。

二、什么場景下會用到OAuth授權

     目前我們大多數的應用場景,也是我們最熟悉的使用環境就是使用第三方登錄,如:微博,QQ,微信,豆瓣等社交平台登錄,互聯網發展到今天,我們也都習慣了這種登錄方式,最大的好處就是便捷,簡化了我們一系列的注冊流程,還有一大堆帳號密碼記不住的困擾,當你碰到一個不支持第三方登錄的網站或者應用的時候,第一感覺就是厭惡,一頓噴。人永遠離不開社交,所以通過社交平台去登錄其他的平台,無疑是最受大家歡迎的方式了。  

  就拿CSDN為例,CSDN是支持第三方平台登錄的,截圖如下:

若用戶想使用QQ登錄,那么在傳統的認證模式中,客戶端(CSDN)請求訪問服務器上受限的資源(QQ),需要通過資源所有者(用戶的QQ賬戶)的憑證在服務器上進行認證。為了支持第三方應用程序(對於QQ來說,CSDN是第三方應用程序,是CSDN去請求訪問QQ的資源)訪問受限資源,資源所有者需要向第三方應用共享其憑證(如用戶QQ的帳號和密碼)。那這樣就會造成以下幾個問題:

  • 第三方應用(CSDN)為了以后繼續使用,那么會存儲資源所有者的憑證,如密碼;
  • 服務端需要支持密碼認證,盡管密碼認證不安全;
  • 第三方應用若想訪問資源所有者的其他資源,資源所有者無法對其進行限制;
  • 資源所有者無法收回第三方的訪問權限,除非用戶主動修改密碼;
  • 如果此時第三方的數據泄漏,那也會導致資源所有者其他數據的泄漏,造成重大損失。

    若此時,CSDN知道了用戶的QQ密碼,那CSDN可以任意去訪問該用戶的所有信息,而QQ無法去限制它的訪問,這不管是對QQ還是用戶本身都會是一件可怕的事,作為使用者,你永遠都無法知道應用都干了些什么。由此OAuth2.0的出現,就是為了解決這樣的問題。

三、OAuth 2.0中的4個成員

在OAuth2.0中有4個成員,Resource Owner、Resource Server、Client、Authorization Server,如圖所示:

在上面4個成員中,授權服務器可能與資源服務器在同一台服務器。

四、OAuth 2.0授權流程

    流程如下,圖片來自RFC6749:

流程解析:

  1. 用戶打開客戶端,客戶端要求向資源所有者(即用戶)給予授權;
  2. 用戶同意授權;
  3. 客戶端得知用戶同意授權后,向授權服務器獲取授權;
  4. 授權服務器給予客戶端授權,並將授權碼(Access Token);
  5. 客戶端攜帶授權碼去請求資源服務器;
  6. 資源服務器將受限的資源開放給客戶端。

五、OAuth 2.0授權模式

    授權許可是表示客戶用來獲取訪問令牌的資源所有者授權的憑證。此規范協議規定了4種授權類型:

  • authorization code(授權碼模式)
  • implicit(簡化模式)
  • resource owner password credentials(密碼模式)
  • client credentials(客戶端模式)

下面詳細說明各種授權模式的具體流程:

  1、authorization code(授權碼模式)

授權代碼授權類型用於獲取訪問令牌和刷新令牌,並針對機密客戶端進行優化。它是一個基於重定向的流程,因此客戶端必須能夠與資源所有者的用戶代理(通常是Web瀏覽器)並且能夠從授權服務器接收傳入請求(通過重定向)。授權碼模式是功能最完整、流程最嚴密的授權模式,它的特點就是通過客戶端的后台服務器,與"服務提供商"的授權服務器進行互動。授權流程如下:

流程解析:

  1. 客戶端通過用戶代理,重定向請求授權服務器,所需參數:客戶端標識及重定向URL;
  2. 用戶選擇是否給予客戶端授權;
  3. 授權服務器給予客戶端一個認證授權碼,並跳轉到指定的URI;
  4. 客戶端使用該授權碼,重定向到授權服務器,獲取令牌;
  5. 授權服務器校驗該授權碼以及重定向的URI后,向客戶端發送令牌或者更新令牌。

以上均個人解釋,簡化了RFC6749官方文檔說明,大致意思是一樣的。注意的一點是,在用戶同意授權后,授權服務器並未直接將令牌發送給客戶端,而是先向客戶端發送了一個授權碼,authorization code,然后再攜帶該授權碼,再一次請求授權服務器,校驗無誤后,再發送令牌(access token),這一步是在后台自動完成的,這樣也使OAuth授權更加安全。

    在該授權流程中,我們所需的幾個參數,官方文檔中要求指定的參數如下:

  • response_type 必選項 表示的是要求指定的授權類型,此處必須設置為:code
  • client_id 必選項 客戶端的唯一標識
  • redirect_uri 可選項 重定向的URI
  • scope 可選項 授權的管道
  • state 建議項 表示客戶端狀態,授權服務器會將該狀態原值返回

看完該流程以及所需的參數后,我們結合實際情況,還是上面提到的例子,以CSDN使用QQ登錄為例,看一下該過程:

(A步驟)點擊QQ登錄,跳轉到QQ帳號安全登錄界面,即騰訊的互聯平台,我們可以直接拿到此時CSDN要請求的地址:

https://graph.qq.com/oauth2.0/show?which=Login&display=pc&

response_type=code&

client_id=100270989&

redirect_uri=https://passport.csdn.net/account/login?oauth_provider=QQProvider&

state=test

這樣我們可以很清楚的看到在上面的URL中,發起了一個get請求,他的授權類型為code 授權碼模式,以及client_id,redirect_uri,state等信息,而此時頁面也跳轉到了用戶代理的頁面,讓用戶去決定是否要同意授權 :

(C步驟)當用戶輸入用戶名密碼后點擊授權並登錄,服務器會先驗證你輸入的是否正確,如果正確,頁面就會跳轉到redirect_uri的地址中,而在這個過程中發生的變化是這樣的,我們繼續查看這時的URL地址:

https://passport.csdn.net/account/login?oauth_provider=QQProvider&

code=D185F3ED93E4F1B3C5F557E6112C7A9B&

state=test

(D步驟)我們可以看到授權並登錄后它重定向到了我們指定的地址,而且還給予了一個code授權碼,另外state狀態還是在請求登錄時的狀態,在下一個步驟中,是客戶端向授權服務器申請令牌,包含以下參數:

  • grant_type 表示授權模式,此處固定為authorization_code,必選
  • code 表示上一步獲取到的授權碼,必選
  • redirect_uri 表示重定向URI,必選
  • client_id 表示客戶端ID,必選

在使用騰訊開放平台時,它會要求有一個client_secrect,是對應你客戶端ID的一個私鑰,它也是在客戶端注冊時產生的,所以在使用QQ登錄獲取令牌時,也必須指定該選項:client_secret,具體的可以看騰訊的開發文檔。那么實際上申請令牌的這個過程我們是看不到的,返回authorization code 后,我們會看到我們的客戶端此時已經登錄成功了。例如:

POST /token HTTP/1.1

Host: graph.qq.com/oauth2.0/token

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA

&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb&client_secret=fdhsjfdsj32jjfhjdk

(E步驟)若以上返回成功,那么在E步驟中會返回如下信息:

HTTP/1.1 200 OK

Content-Type: application/json;charset=UTF-8

Cache-Control: no-store

Pragma: no-cache

 

{

"access_token":"2YotnFZFEjr1zCsicMWpAA",

"token_type":"example",

"expires_in":3600,

"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",

"example_parameter":"example_value"

}

里面包含了我們所需要的令牌access token以及有效期等信息。實際上在我們實際應用過程中,我們不止是到這里就結束了,我們會使用access token令牌再去請求資源服務器,獲取可以被調用的資源,以及一些其他的操作。

  2、implicit(簡化模式)

簡化模式用於獲取訪問令牌(但它不支持令牌的刷新),並對運行特定重定向URI的公共客戶端進行優化,而這一些列操作通常會使用腳本語言在瀏覽器中完成,令牌對訪問者是可見的,且客戶端也不需要驗證。具體流程如下:

步驟解析:

  1. 客戶端攜帶客戶端標識以及重定向URI到授權服務器;
  2. 用戶確認是否要授權給客戶端;
  3. 授權服務器得到許可后,跳轉到指定的重定向地址,並將令牌也包含在了里面;
  4. 客戶端不攜帶上次獲取到的包含令牌的片段,去請求資源服務器;
  5. 資源服務器會向瀏覽器返回一個腳本;
  6. 瀏覽器會根據上一步返回的腳本,去提取在C步驟中獲取到的令牌;
  7. 瀏覽器將令牌推送給客戶端。

(A步驟)中需要用到的參數,注意在這里要使用"application/x-www-form-urlencoded"格式:

  • response_type 必選項,此值必須為"token"
  • client_id 必選項
  • redirect_uri 可選項
  • scope 可選項
  • state 建議選項

    例如:

GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz 
 &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 
 Host: server.example.com 

    (C步驟)中返回的參數包含:

  • access_token 必選項
  • token_type 必選項
  • expires_in 建議選項
  • scope 可選項
  • state 必選項

    例如:

HTTP/1.1 302 Found 
 Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA 
 &state=xyz&token_type=example&expires_in=3600 

  3、resource owner password credentials(密碼模式)

密碼模式適合建立在客戶端與資源所有者具有信任關系的情況下,例如它是一個設備的操作系統或者具有很高權限的應用。這種模式用戶要向客戶端提供自己的用戶名密碼,從而達到向服務提供商索取授權。授權服務器在啟動此類型時,要特別小心,只有在其他的授權方式不被允許的情況下才可以使用這種授權模式。流程如下:

  1. 客戶端要求使用資源所有者的密碼;
  2. 資源所有者給予用戶名密碼后,客戶端向授權服務器發起申請令牌的請求;
  3. 授權服務器將令牌發放給客戶端。

步驟解析:

(B步驟)所需參數:

  • grant_type 必選項 此值必須為"password"
  • username 必選項 用戶名
  • password 必選項 密碼
  • scope 可選項

例如:

POST /token HTTP/1.1

Host: server.example.com

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

Content-Type: application/x-www-form-urlencoded

grant_type=password&username=johndoe&password=A3ddj3w

    (C步驟)發放令牌:

HTTP/1.1 200 OK 
 Content-Type: application/json;charset=UTF-8 
 Cache-Control: no-store 
 Pragma: no-cache 

 

 { 
 "access_token":"2YotnFZFEjr1zCsicMWpAA", 
 "token_type":"example", 
 "expires_in":3600, 
 "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", 
 "example_parameter":"example_value" 
 }

  4、client credentials(客戶端模式)

客戶端模式是4種模式中最簡單的一種模式。客戶端可以使用客戶端憑據請求訪問令牌(或者其他支持的認證方式),在這種模式中,客戶端占據主導地位,它不需要用戶的同意,可以直接向授權服務器索取令牌,嚴格來說,該模式並不存在授權的問題,流程如下:

  1. 客戶端向授權服務器發起請求索要令牌;
  2. 授權服務器將令牌發放給客戶端。

步驟解析:

(A步驟)中所需的參數::

  • grant_type 必選項 此值必須為client_crendentials
  • scope 可選項

例如:

POST /token HTTP/1.1

Host: server.example.com

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

(B步驟)授權服務器返回結果:

HTTP/1.1 200 OK

Content-Type: application/json;charset=UTF-8

Cache-Control: no-store

Pragma: no-cache

{

"access_token":"2YotnFZFEjr1zCsicMWpAA",

"token_type":"example",

"expires_in":3600,

"example_parameter":"example_value"

}

六、小結

    以以上內容簡要介紹了關於OAuth授權的一些基礎知識以及各種授權模式的具體流程。在后面的文章中,會結合本篇內容,陸續講解如何在.net core中借助IdentityServer4 使用 OAuth 2.0授權。

掃描二維碼關注我的公眾號,共同學習,共同進步!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM