日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

從事互聯(lián)網(wǎng)開發(fā)的同學們應該或多或少聽說過 OAuth2.0 協(xié)議,例如使用微信或支付寶賬戶登錄第三方App,這是 OAuth2.0 最為開發(fā)人員所熟知的一個用途,但是圍繞著 OAuth2.0 協(xié)議其實還有很多有意思的內(nèi)容可以挖掘,我們可以用它以及它的擴展協(xié)議來做許多有用的東西。因此我打算寫一個系列來詳細介紹 OAuth2.0 以及圍繞它所產(chǎn)生的一些擴展協(xié)議和優(yōu)良實踐。

如果你正想要設計一個基于 OAuth2.0 協(xié)議的授權服務架構來對外提供一些資源或服務,那么本系列文章將有助于你實現(xiàn)這一目標。

本文是本系列的第一篇,我會比較詳細地帶你解讀 OAuth2.0 協(xié)議。本文會從基礎概念和術語開始講起,讓你逐漸了解 OAuth2.0 的核心理念以及它所要解決的問題,然后將會用一多半的篇幅來詳細闡述4大流程模式中使用最廣的授權碼模式,我會介紹它的流程、接口、錯誤處理、注意事項等。

注:本文涉及到 OAuth2.0 協(xié)議的所有內(nèi)容全部來自于 RFC 6749 The OAuth 2.0 Authorization Framework ,也就是說全部都是第一手的解讀。

什么是授權、授權認證、資源外放?

什么是授權?要解釋這個問題,先要引入一個概念——資源。信息或者數(shù)據(jù)就是一種資源,例如用戶的身份信息、用戶的相冊數(shù)據(jù)、評論記錄、收藏的網(wǎng)站等等,除了信息或數(shù)據(jù)之外,完成某項特定操作的能力也是一種資源,通常以API的形式出現(xiàn),例如發(fā)送短信、上傳頭像、發(fā)布vlog等等,這些都是API也是資源。有些資源需要用戶的授權(如獲得用戶身份信息),而另一些資源不需要得到用戶的授權(如發(fā)送短信),我們今天所討論的,是需要用戶授權的那一類——畢竟這些資源的所有權屬于用戶。

在什么時候需要授權呢?我們來假設一個場景,我們大部分開發(fā)者都有Github賬號(假裝大家都有),但是由于某些原因,Github以前并不提供移動版的官方客戶端,但廣大群眾需要在移動端使用Github的呼聲很強烈,這怎么辦呢?Github的做法是,雖然我不提供官方的app,但是我提供用于管理用戶資源的APIs,這些APIs包含了用戶認證信息(user)、倉庫(repositories)、訂閱者(followers)、已訂閱(following)、星標(starred)記錄等等幾乎全部的數(shù)據(jù),這樣就可以吸引那些熱心的開發(fā)者為他編寫非官方的客戶端程序,或者其它有用的應用。那么是不是所有人或程序都能毫無限制的去使用這些 APIs 呢?顯然是不可以的,那么Github就需要通過某種機制來保護這些APIs,使得調(diào)用者必須要在用戶的允許(consent)之下才能夠進行調(diào)用。那么授權的含義就很容易理解了——即調(diào)用者(client)獲取用戶的“允許”以訪問用戶的數(shù)據(jù)的過程就稱為“授權”。

我們現(xiàn)在明白什么是授權了,那么授權認證是什么意思呢?授權認證其實就是授權當中的一類特殊情況,即調(diào)用者(client)所要申請訪問的資源屬于用戶身份信息(或稱為認證信息)且調(diào)用者(client)使用此資源的目的在于幫助其(client)對用戶進行認證時,這種特殊的授權行為又稱為授權認證。

什么是資源外放?在上文中,Github網(wǎng)站提供了用于訪問用戶數(shù)據(jù)的API的行為就屬于資源外放。資源外放通常要搭配授權協(xié)議一起實施。


什么是授權協(xié)議、OAuth2.0?

什么是協(xié)議?協(xié)議就是標準,就是一套規(guī)則體系。上文中,用于規(guī)定授權操作的流程、接口、錯誤處理方式等等規(guī)則的集合,就是一個授權協(xié)議。目前互聯(lián)網(wǎng)上使用最廣的授權協(xié)議是OAuth2.0。

OAuth2.0是由IETF(互聯(lián)網(wǎng)工程小組)編纂并維護的一套授權協(xié)議,是目前業(yè)界的事實標準。

國內(nèi)的微信、支付寶,國外的微軟、谷歌等等巨頭,都采用了此協(xié)議來對外提供API資源。

在這里我有必要強調(diào)一點,OAuth2.0 并不是一個認證協(xié)議,它不是被設計為解決認證問題的,如果你希望設計一個認證架構,那么你應該考慮 OpenID Connect (OIDC) 協(xié)議,它是 OAuth2.0 的衍生協(xié)議,由 OpenID 發(fā)起并維護,目前已得到很多大型互聯(lián)網(wǎng)公司的支持,例如谷歌、微軟、蘋果、亞馬遜。而如果你要學習 OIDC 協(xié)議,那么我建議你也應該從 OAuth2.0 協(xié)議開始。

OAuth2.0 關鍵概念和術語

從這一段開始,我們來正式講解 OAuth2 協(xié)議,首先來介紹一下此協(xié)議有哪些重要的概念或術語。

Resource Owner

資源擁有者,即用戶

Resource Server

資源服務器,即存儲用戶資源的服務器,通常以 API 的形式暴露服務,它會在驗證 Access Token 通過后為調(diào)用者提供用戶資源

Client

客戶端,即申請用戶授權的主體,可以是前端程序 —— 如 JAVAScript 應用、移動端原生 App 等等,也可以是服務器端應用程序 —— 如 Java 程序

Authorization Server

授權服務器(簽發(fā)授權碼和訪問令牌)

Access Token

訪問令牌,拿到此令牌即可訪問 Resource Server 中的用戶資源

Refresh Token

刷新令牌,用來獲得新的 Access Token ,有時 Authorization Server 會在簽發(fā) Access Token 的同時也附加一個 Refresh Token ,這樣 Client 就不必每次都去詢問用戶獲得授權了

Client Type

客戶端類型,分為 Public 和 Confidential 兩種

Client Identifier

客戶端標識,即 client_id ,唯一標識一個 Client

Client Authentication

客戶端認證,對 Public 類型的 Client 采用 PKCE 的方式認證,而對 Confidential 類型的 Client 一般會采用 Basic 方式或基于非對稱算法的 JWT 方式來進行認證。

OAuth2.0 基本流程

盡管網(wǎng)絡上很多作者都會直接開始講解授權碼模式的流程圖,但我認為還是有必要先了解 OAuth2.0 最最基本的抽象流程圖,它是所有具體流程模式的抽象概括版,可以讓我們跳出具體的流程模式并站在一定高度上來審視 OAuth2.0 協(xié)議究竟是什么,解決了哪些問題,對于你理解一些關于 OAuth2.0 的誤區(qū)是有幫助的,如下圖:

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

OAuth2.0 抽象流程圖

圖片來自 RFC6749 - The OAuth 2.0 Authorization Framework

上圖展現(xiàn)了 OAuth2.0 協(xié)議的本質(zhì),它概括為3個步驟:申請授權、獲得授權、訪問資源。 OAuth2.0 的所有流程模式(除了早先的四大模式之外還有谷歌的設備碼模式)都是這3個步驟的具體表現(xiàn)形式。

網(wǎng)絡上很多教程會一上來就給你看授權碼模式的流程圖,而我必須要說明一點,授權碼模式不等同于 OAuth2.0 協(xié)議的全部,盡管該模式的確是使用最多的一種流程模式,但它只是一種流程模式,不是此協(xié)議的本質(zhì)。

如果跳過上面的抽象流程圖而直接開始講授權碼模式、簡化模式等流程模式,那么有一個很大的壞處就是,它會使你誤認為 OAuth2.0 是一個認證協(xié)議,因為授權碼模式(還有簡化模式)中帶有認證過程,即 Authorization Server 會對 User 進行認證,認證之后才會有授權碼 code 和 Access Token ,這會讓你誤以為拿到 code 或 Access Token 就代表用戶已得到認證,你就可以拿到用戶的身份信息了,但在抽象流程圖中并沒有出現(xiàn)“認證 Authentication”的字眼。Access Token 壓根就不是一個表示認證信息的令牌,它是一個授權令牌,它只能表示一個 Client 確實獲得了某用戶的某項資源的訪問權限,但這既不能體現(xiàn)用戶的登錄狀態(tài),亦不表示一定能夠獲得用戶的身份信息,例如使用 Refresh Token 就可以刷新得到一個新的 Access Token ,而這個過程是不需要用戶參與的。


授權碼模式 Authorization Code

基本流程

授權碼模式是應用最廣泛的一種流程模式,它可以應用于任何有 Web 支持的平臺,例如傳統(tǒng) Web 網(wǎng)站,單頁應用 SPA ,移動端原生 App 等等,它的流程圖如下:

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

OAuth2.0 授權碼模式流程圖

分步驟講解:

A) 客戶端程序( Client )向資源擁有者( Resource Owner )申請授權,并指定一個回跳地址用于接收接下來所產(chǎn)生的授權碼或錯誤信息

B) 資源擁有者同意授權,并返回一個憑證給客戶端程序,這個憑證就是授權碼 code

C) 客戶端程序拿到授權憑證(即授權碼 code )后向授權服務器(Authorization Server)申請 Access Token

D) 授權服務器驗證客戶端程序提供的授權憑證后返回 Access Token 給到客戶端 Client

E) 客戶端程序 Client 使用 Access Token 訪問資源服務器(Resource Server)中的用戶資源

F) 資源服務器驗證 Access Token 后返回受保護的資源

以上描述中注意客戶端程序并不是指 C-S 架構下的 Client 客戶端,它在這里既可以指前端程序(如 SPA 或 APP ),也可以指WEB網(wǎng)站的后臺服務器(如 Java Web 應用)

在授權碼模式中,我們可以看到 Authorization Server 提供了2個接口( Endpoint ),即申請授權接口與獲得授權令牌接口,對應的分別是申請授權與獲得授權這兩個步驟。下面我們來詳細看一下這兩個接口都定義了哪些內(nèi)容以及它們的使用方法。

注意:OAuth2.0 及其擴展協(xié)議中所涉及的所有接口( Endpoint )全部都是 HTTP 接口

申請授權接口 Authorization Endpoint

申請授權接口的請求 Authorization Request

首先,Client 需要先構建一個用于跳轉(zhuǎn)的 uri 地址,這個地址是由 Authorization Server 即授權服務器提供的,Client 需要在它的后面拼接如下這些參數(shù)(使用 application/x-www-form-urlencoded 編碼方式對參數(shù)進行編碼):

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

申請授權接口的請求參數(shù)

然后 Client 要控制用戶的 User-Agent (一般就是瀏覽器)跳轉(zhuǎn)到剛剛構建的 uri 上去,下面是一個例子:

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

申請授權接口的請求例子

在此接口中,有如下幾點規(guī)則需要注意:

  • 注意以上參數(shù)是拼接在 uri 后面的,不是在 http body 中的,編碼格式是 application/x-www-form-urlencoded
  • 授權服務器 Authorization Server 收到請求后,應驗證該請求是否正確,例如 client_id 是否存在, redirect_uri 是否合法等等
  • 如果請求正確,則授權服務器 Authorization Server 需要先認證用戶(如果有必要)并詢問用戶以獲得用戶的授權決定 authorization decision ,一般常見的方式就是顯示一個授權頁面,用戶可以同意授權,也可以拒絕授權
  • 當用戶做出授權選擇后,授權服務器 Authorization Server 應當控制 User-Agent (瀏覽器)去跳轉(zhuǎn)到前面參數(shù)中的 redirect_uri 中,如果用戶選擇了同意授權,那么跳轉(zhuǎn)地址后面要附帶授權碼 code 和隨機數(shù) state (如果請求中有),關于這兩個參數(shù)請參見下面的表格“申請授權接口的響應參數(shù)(同意授權的情況)”
  • 如果用戶拒絕授權,或者授權過程出現(xiàn)了錯誤,則授權服務器應當參照下面的錯誤處理方式來處理,關于相關參數(shù)和錯誤代碼值請參見下面的表格“申請授權接口的響應參數(shù)(授權失敗的情況)”
  • 請?zhí)貏e留意一下 state 這個參數(shù),它可以用來防止 CSRF 攻擊,具體的攻擊方式本文就不介紹了,你可以自行搜索。state 參數(shù)是由 client 生成,最終由 client 完成校驗的。在本接口處理完成后(不論是成功或發(fā)生錯誤),在重定向回 redirect_uri 的時候應當帶上 state 參數(shù)(如果有就必須帶上)。
  • 控制 User-Agent 跳轉(zhuǎn)的方式可以是 302 重定向,也可以是其他方法,比如 JavaScript 跳轉(zhuǎn)等

申請授權接口的響應(授權成功的情況) Authorization Response

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

申請授權接口的響應參數(shù)(同意授權的情況)


你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

申請授權接口的響應例子(同意授權的情況)

申請授權接口的響應(授權失敗的情況) Authorization Error Response

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

申請授權接口的響應參數(shù)(授權失敗的情況)


你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

申請授權接口的錯誤代碼值


你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

申請授權接口的響應例子(授權失敗的情況)

很多人在實現(xiàn) OAuth2.0 的過程中往往會忽視對于錯誤情況的處理,其實 OAuth2.0 已經(jīng)規(guī)定了錯誤處理方式了,如果你的目標是要建立一個標準的 OAuth2.0 服務,那么別忽視錯誤處理這一環(huán)。

返回錯誤信息時要特別注意的幾點

  • 每個 client 在注冊時應指定它所能使用的 redirect_uri ,Authorization Server 應保存下來這些 redirect_uri ,并在本接口被調(diào)用時驗證 client_id 與 redirect_uri 是否匹配,以此來避免惡意攻擊。
  • 如果 redirect_uri 與 client_id 匹配,則依據(jù)上圖把相應的錯誤信息拼接在給定的回跳地址 redirect_uri ,并控制 User-Agent 重定向到該地址;
  • 但如果 redirect_uri 與 client_id 不匹配,或者違反了黑名單或白名單的規(guī)則(這個規(guī)則是你可以自己設計的),那么不應該做跳轉(zhuǎn),而應當在授權服務器上給予適當提示。
  • 只要 redirect_uri 沒有問題,那么所有類型的錯誤,都應該發(fā)送給 client ,讓 client 能夠感知到錯誤的發(fā)生,并依據(jù)錯誤類型給用戶良好的錯誤信息展示,而不是由 Authorization Server 去顯示這些錯誤。

獲取訪問令牌接口 Access Token Endpoint

獲取訪問令牌接口的請求 Access Token Request

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

獲取訪問令牌接口的請求參數(shù)


你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

獲取訪問令牌接口的請求例子

注意:在請求中,注意編碼格式 Content-Type 是 application/x-www-form-urlencoded ,并且 method 是 POST ,這與下面的響應是不一樣的。

在此接口中,授權服務器 Authorization Server 必須滿足以下幾點:

  • 授權服務器必須對 Client 進行認證,Confidential 類型的 Client 可以采用 Basic 方式來認證,關于 Basic 認證方式請自行搜索一下;當然也可以使用基于非對稱加密算法的 JWT 令牌來認證;而 Public 類型的 Client 如果要使用此接口,則必須實現(xiàn) PKCE 協(xié)議,關于 PKCE 我會在以后的文章中專門討論,你也可以自行搜索一下
  • 授權服務器必須確保請求參數(shù)中的 code 和 client_id 是匹配的,換句話說, code 確實是簽發(fā)給請求中的 client_id 的
  • 確保 code 是有效的,有效包含2層含義 —— code 確實是授權服務器簽發(fā)的、code 仍在有效期內(nèi)
  • 如果前面的“申請授權接口的請求 Authorization Request”中有 redirect_uri ,那么本接口中也應當包含 redirect_uri ,并且值必須是一致的。這一點在很多其它博客上很容易忽視,但它很重要

獲取訪問令牌接口的響應

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

獲取訪問令牌接口的響應參數(shù)(成功的情況)

注意, expires_in 的單位是秒,如果你不返回此參數(shù),則應當與 Client 約定一個默認值,并在文檔中注明。

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

獲取訪問令牌接口的響應例子(成功的情況)

關于獲取訪問令牌接口的響應,有以下幾點要注意:

  • 返回的參數(shù)必須以 JSON 格式放到 HTTP Response Entity-Body 中,也就是報文體中,Content-Type 必須是 application/json (后面的字符集可以加上也可以不加上)
  • 上面參數(shù)表中定義的參數(shù)必須放在 JSON 結構的最頂層,換句話說就是不要搞嵌套
  • 除了上面表格中規(guī)定的參數(shù),你可以附加別的參數(shù)

上面是授權成功的情況,那么授權失敗的情況呢?

你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

獲取訪問令牌接口的響應參數(shù)(失敗的情況)


你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

獲取訪問令牌接口的錯誤代碼值


你真的理解OAuth2.0協(xié)議嗎?深入解讀OAuth2.0協(xié)議

獲取訪問令牌接口的響應例子(錯誤的情況)

關于本接口在錯誤情況下的響應,有以下幾點要注意:

  • 在錯誤情況下,本接口依然要以 JSON 的格式來返回錯誤信息,即 Content-Type 是 application/json (后面的字符集可以加上也可以不加上)
  • HTTP Status 狀態(tài)碼是 400 ,注意不是 200 ;我知道很多開發(fā)者習慣于不論什么情況,都返回 200 ,然后在 HTTP Response Entity-Body 中的 JSON 報文里添加一個狀態(tài)字段,但在本接口里,是通過 HTTP Status 來表達錯誤的,請一定注意這一點

現(xiàn)在 Client 獲得了 Access Token 之后,就可以去訪問受保護資源了,而 Resource Server 要如何校驗 Access Token 呢?其實這一點最開始 ITEF 并沒有歸納到協(xié)議中,而是通過另外一個協(xié)議來將此內(nèi)容補充上了,請參見 RFC 7662 - OAuth 2.0 Token Introspection

結語

至此,我們已經(jīng)介紹完了 OAuth2.0 協(xié)議的基礎知識和授權碼模式,其實 OAuth2.0 協(xié)議還有非常多值得挖掘的細節(jié),以及很多擴展或衍生協(xié)議,來幫助你在各種不同的平臺上使用這個協(xié)議來完成授權或授權認證的工作,我會在其它文章中陸續(xù)為大家解讀 OAuth2.0 協(xié)議的方方面面。

如果本文中有哪些地方你沒有讀懂,或希望重點展開的,歡迎給我留言。另外如果你發(fā)現(xiàn)本文存在紕漏,也歡迎隨時給我留言,共同學習。

分享到:
標簽:OAuth2
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定