【全棧修煉】OAuth2 修煉寶典

1、OAuth 概念

開放受權(OAuth)是一個開放標準,容許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯繫人列表),而無需將用戶名和密碼提供給第三方應用。 —— 維基百科html

嚴格來講,OAuth2 不是一個標準協議,而是一個安全的受權框架。其詳細描述系統中不一樣角色,用戶,服務前端應用(如 API )以及客戶端(如網站或APP)之間如何實現相互認證前端

當前 OAuth 協議版本是 OAuth2.0,須要注意的是,OAuth2.0 並不向下兼容 OAuth1.0。git

在生活中,比較常見的 OAuth2 的使用場景是受權登陸,而且也普遍應用於 web、桌面應用和移動 APP 的第三方服務提供受權登陸驗證機制,以實現不一樣應用直接數據訪問的權限github

2、OAuth2 重點名詞介紹

在 OAuth2 標準中定義瞭如下四種角色:web

  • 資源擁有者 (Resource Owner):

表明受權客戶端訪問自己資源信息的用戶(User);後端

  • 客戶端 (Client):

表明意圖訪問受限資源的第三方應用。瀏覽器

  • 資源服務器 (Resource Server):

表明託管了受保護的用戶帳號信息的服務器,它與認證服務器,能夠是同一臺服務器,也能夠是不一樣的服務器;安全

  • 受權服務器 (Authorization Server):

表明驗證用戶身份而後爲客戶端派發資源訪問令牌的服務器,即服務提供商專門用來處理認證的服務器;服務器

3、OAuth2 運行流程

1. 流程分析

20191028-OAuth2-01.png

(配圖來自阮一峯大佬微信

大體流程歸納就是:

  • (A)Authrization Request

用戶打開客戶端之後,客戶端要求用戶給予受權。

  • (B)Authorization Grant(Get)

用戶贊成給予客戶端受權。

  • (C)Authorization Grant(Post)

客戶端向受權服務器發送它本身的客戶端身份標識和上一步中得到的受權(authorization grant),向認證服務器申請令牌。

  • (D)Access Token(Get)

認證服務器對客戶端進行認證之後,確認無誤,贊成發放令牌(access token),受權階段至此所有結束。

  • (E)Access Token(Post && Validate)

客戶端使用令牌,向資源服務器申請獲取資源。

  • (F)Protected Resource(Get)

資源服務器確認令牌無誤,贊成向客戶端開放資源。

理解完上面整個流程之後,咱們再看看下面這張圖,能更加清晰理解 OAuth2 的整個運行流程:

20191028-OAuth2-02.png

(配圖來自公衆號前端修仙之路

從整個流程能夠看出,在 B 步驟最爲關鍵,即須要獲取到用戶對客戶端的受權(如咱們在微信掃碼登陸時,點擊「肯定」按鈕的步驟)。

有了這個受權之後,客戶端才能拿到令牌,進而憑令牌向資源服務器獲取資源。

2. 案例:微信登陸

另外,微信登陸的實現流程也相似:

20191028-OAuth2-03.png

(配圖來自微信官方文檔

其總體流程爲:

  1. 第三方發起微信受權登陸請求,微信用戶容許受權第三方應用後,微信會拉起應用或重定向到第三方網站,而且帶上受權臨時票據 code 參數;

  2. 經過 code 參數加上 AppIDAppSecret 等,經過 API 換取 access_token

  3. 經過 access_token 進行接口調用,獲取用戶基本數據資源或幫助用戶實現基本操做

3. OAuth2 優缺點

  • 優勢:

適合快速開發實施,代碼量少,API須要被不一樣APP使用,且每一個APP使用方式也不一樣的狀況。

  • 缺點:

學習和理解的成本比較大,而且 OAuth2 不是一個嚴格的標準協議,在實施過程當中更容易出錯。

4、OAuth2 四種受權模式

經過前面描述,能夠知道OAuth 的核心就是向第三方應用頒發令牌。

OAuth 2.0 規定了四種得到令牌的流程。你能夠選擇最適合本身的那一種,向第三方應用頒發令牌。即如下四種受權方式:

  • 受權碼(authorization-code)
  • 隱藏式(implicit)
  • 密碼式(password)
  • 客戶端憑證(client credentials)

注意:

無論哪種受權方式,第三方應用申請令牌以前,都必須先到系統備案,說明本身的身份,而後會拿到兩個身份識別碼:客戶端 ID(client ID)客戶端密鑰(client secret)

這是爲了防止令牌被濫用,沒有備案過的第三方應用,是不會拿到令牌的。

1. 受權碼(authorization code)

第三方應用先申請一個受權碼,而後再用該碼獲取令牌

適用於有後端的 Web 應用,受權碼經過前端傳送,令牌則是儲存在後端,並且全部與資源服務器的通訊都在後端完成。這樣的先後端分離,能夠避免令牌泄漏。

這種方式也是最經常使用的流程,安全性最高

總體流程

20191028-OAuth2-04.png

(配圖來自阮一峯大佬

步驟分析

  1. 用戶從 A 網站跳轉到 B 網站,請求用戶確認受權,以獲取受權碼,其發送連接示意以下:
https://b.com/oauth/authorize?
       response_type=code&
       client_id=CLIENT_ID&
       redirect_uri=CALLBACK_URL&
       scope=read
複製代碼

其中:

response_type 參數表示要求返回受權碼(code);

client_id 參數讓 B 知道是誰在請求;

redirect_uri 參數是 B 接受或拒絕請求後的跳轉網址;

scope 參數表示要求的受權範圍(這裏是只讀);

  1. 在 B 網站中,當用戶贊成受權 A 網站,則 B 網站會攜帶受權碼,重定向到 redirect_uri 參數指定的網址,就像下面這樣:
https://a.com/callback?code=AUTHORIZATION_CODE
複製代碼
  1. A 網站獲取受權碼之後,在 A 網站後端中向 B 網站請求令牌:
https://b.com/oauth/token?
       client_id=CLIENT_ID&
       client_secret=CLIENT_SECRET&
       grant_type=authorization_code&
       code=AUTHORIZATION_CODE&
       redirect_uri=CALLBACK_URL
複製代碼

client_id 參數和 client_secret 參數用來讓 B 確認 A 的身份( client_secret 參數是保密的,所以只能在後端發請求);

grant_type 參數的值是 AUTHORIZATION_CODE ,表示採用的受權方式是受權碼;

code 參數是上一步拿到的受權碼;

redirect_uri 參數是令牌頒發後的回調網址;

  1. B 網站接受請求並驗證身份,身份驗證經過後,會發放令牌。向redirect_uri 指定的網址,發送包含令牌 access_token 字段的JSON數據,流程完畢。

2. 隱藏式(implicit)

隱藏受權碼步驟,直接向前端發放令牌,也稱受權碼隱藏式。

總體流程

20191028-OAuth2-05.png

(配圖來自阮一峯大佬

步驟分析

  1. 用戶從 A 網站跳轉到 B 網站,要求受權用戶數據給 A 網站使用。
https://b.com/oauth/authorize?
  response_type=token&
  client_id=CLIENT_ID&
  redirect_uri=CALLBACK_URL&
  scope=read
複製代碼

response_type 參數爲 token,表示要求直接返回令牌

  1. 用戶在 B 網站贊成受權給 A 網站。

當用戶贊成受權後,會跳轉到 redirect_uri 參數指定的重定向地址,並將令牌做爲 URL 參數傳遞給 A 網站。

https://a.com/callback#token=ACCESS_TOKEN
複製代碼

token 參數就是令牌,A 網站所以直接在前端拿到令牌。

注意:

這裏的令牌位置是 URL 錨點(即 # 號),而不是查詢字符串,這是由於錨點不會發到服務器,避免泄露令牌的風險。

適用場景:

因爲直接傳遞令牌不安全,所以經常適用在對安全要求不高的場景,而且令牌有效期很是短,例如會話期間(session)有效,關閉瀏覽器便失效。

3. 密碼式(password)

即:對於信任的應用,能夠攜帶約定的用戶名和密碼進行令牌申請

流程分析

20191028-OAuth2-07.png

  1. A 網站使用 B 網站提供的用戶名和密碼,向 B 網站發起令牌請求。
https://oauth.b.com/token?
  grant_type=password&
  username=USERNAME&
  password=PASSWORD&
  client_id=CLIENT_ID
複製代碼

grant_type 參數是受權方式,這裏的 password 表示"密碼式"; usernamepassword 是 B 的用戶名和密碼。

  1. B 網站驗證身份後直接將令牌存在 JSON 數據中,做爲 HTTP 相應返回令牌給 A 網站。

適用場景:

風險較大,通常適用在對應用高度信任的狀況。

4. 客戶端憑證(client credentials)

即:給出憑證讓對方確認並提供令牌

流程分析

  1. A 應用在命令行向 B 發出請求。
https://oauth.b.com/token?
  grant_type=client_credentials&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET
複製代碼

grant_type 參數等於 client_credentials 表示採用憑證式; client_idclient_secret 用來讓 B 確認 A 的身份。

  1. B 網站驗證身份後返回令牌。

這種方式給出的令牌,是針對第三方應用的,而不是針對用戶的,即有可能多個用戶共享同一個令牌。

適用場景:

經過命令行請求令牌。

流程分析

20191028-OAuth2-06.png

5、使用令牌

當網站獲取到令牌之後,接下來每一個 API 請求都須要帶上令牌,其作法是在請求的頭信息中,將令牌添加 Authorization 字段中。

6、更新令牌

當令牌有效期到了,OAuth2 容許用戶自動更新令牌,而不用讓用戶從新受權獲取新令牌。

具體流程:

在 B 網站發放令牌時,一次性發放 2 個令牌,一個用於獲取數據,一個用於獲取新的令牌(refresh token 字段)。令牌到期後,用戶使用 refresh token 發送請求去更新令牌:

https://b.com/oauth/token?
  grant_type=refresh_token&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET&
  refresh_token=REFRESH_TOKEN
複製代碼

grant_type 參數爲 refresh_token 表示要求更新令牌; client_id 參數和 client_secret 參數用於確認身份; refresh_token 參數就是用於更新令牌的令牌。

B 網站驗證經過之後,就會頒發新的令牌。

參考文章

  1. 部門內部培訓資料
  2. 《OAuth 2 深刻介紹》
  3. 《阮一峯 理解OAuth 2.0》
  4. 《阮一峯 OAuth 2.0 的四種方式》

關於我

本文首發在 pingan8787我的博客,如需轉載請聯繫本人。

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 github.com/pingan8787/…
ES小冊 js.pingan8787.com

微信公衆號

bg
相關文章
相關標籤/搜索