[认证授权] 1.OAuth2授权
1 OAuth2解決什么問題的?
舉個栗子先。小明在QQ空間積攢了多年的照片,想挑選一些照片來打印出來。然后小明在找到一家提供在線打印并且包郵的網站(我們叫它PP吧(Print Photo縮寫 ))。
那么現在問題來了,小明有兩個方案來得到打印的服務。
針對方案(1):小明要去下載這些照片,然后給PP,小明累覺不愛,,,
針對方案(2):小明交出去自己的QQ賬號密碼,還要告訴PP哪些需要打印,哪些不需要,小明覺得自己有些小秘密不想給PP看,,,
小明覺得很痛苦,,,那么有沒有不給PP賬號密碼,不下載照片,自己選哪些要打印直接扔給PP去打印的辦法呢?OAuth走了過來扔給小明一塊肥皂...
2 OAuth2簡介
總結來說,OAuth2 是一個開放授權標準,它允許用戶(小明)讓第三方應用(PP)訪問該用戶在某服務的特定私有資源(QQ空間中小明的照片,可以不包含小明的小視頻哦)但是不提供賬號密碼信息給第三方應用(PP)。
有個小問題,為啥是OAuth2呢?1在哪?嗯,這個嘛,其實是有1和1.1版本的,只是因為1和1.1版本流程比較復雜,應用不是很廣范,這里就不介紹了。據筆者以前做過的項目,Twitter是使用的OAuth1.1的版本,感興趣的可以去了解下https://dev.twitter.com/oauth。
2.1 OAuth2的四個重要角色
進入正題,在OAuth2的完整授權流程中有4個重要的角色參與進來:
其中Authorization server和Resource server可以是獨立的服務提供商,也可以是在一起的,比如騰訊提供QQ空間作為資源服務器的同時也提供授權服務。
從這里可以看出,OAuth2在解決小明遇到的問題的過程中增加了一個Authorization server的角色。又印證了那句話,在計算機領域的所有問題都可以添加一個中間層來解決。
OAuth2解決問題的關鍵在于使用Authorization server提供一個訪問憑據給Client,使得Client可以在不知道Resource owner在Resource server上的用戶名和密碼的情況下消費Resource owner的受保護資源。
3 部署OAuth2需要的完成的工作
由于OAuth2引入了Authorization server來管理Resource Owner,Client和Resource Server的三角關系,那么想要用上OAuth2,是實現以下功能的。
作為資源服務提供商來說,1,2,3這三件事情是需要完成的。
作為第三方應用程序,要完成的工作是在4和5這兩個步驟中。
其中作為Resource owner來說,是不用做什么的,是OAuth2受益的千千萬萬的最終人類用戶。
3.1 作為Resource server
在一般情況下,Resource server提供Authorization server服務,主要提供兩類接口:
除此之外,還需要提供一個第三方應用程序注冊管理的服務。通常情況下會為注冊完成的第三方應用程序分配兩個成對出現的重要參數:
3.2 作為Client
在Client取得client_id和client_secret之后。使用這些信息來發起授權請求、獲取access_token請求和消費受保護的資源。
4 OAuth2的授權流程
貼個圖瞅瞅OAuth2的工作流程:
在上述的OAuth完整流程中,(A)->(B)->(C)->(D)是授權的過程(參與者有小明,PP,QQ空間,Authorization server);(E)->(F)是消費資源的過程(參與者有PP和QQ空間)。
- (A)小明訪問PP,PP向QQ空間發起授權請求;
- (B)QQ空間接受PP的授權請求,并返回授權許可給PP;
- (C)PP使用授權許可向Authorization server發起請求;
- (D)Authorization server驗證PP的身份和授權許可,發送訪問令牌給PP;
- (E)PP用訪問令牌請求小明存儲在QQ空間的照片;
- (F)QQ空間根據訪問令牌,返回小明的照片信息給PP。
這其中比較重要的一個概念是訪問令牌 ,它代表的信息是整個OAuth2的核心,也是ABCD這些步驟最終要得到的信息。
訪問令牌是對PP可以在QQ空間訪問小明的哪些信息這個完整權限的一個抽象,比如PP要訪問小李在QQ空間的照片,那么就是另外一個訪問令牌了。
訪問令牌背后抽象的信息有哪些呢?如下3類信息。
有了這三類信息,那么資源服務器(Resouce Server)就可以區分出來是哪個第三方應用(Client)要訪問哪個用戶(Resource Owner)的哪些資源(以及有沒有權限)。
5 OAuth2的4種授權許可
上一小節介紹了OAuth2的授權流程,除了訪問令牌之外,還有一個重要的概念授權許可(Authorization Grant)。
書面化的方式解釋就是授權許可是一個代表資源所有者授權(訪問受保護資源)的憑據,客戶端用它來獲取訪問令牌。讀起來比較抽象,翻一下就是授權許可是小明授予PP獲得QQ空間訪問令牌的一個憑據。
那么如何獲得這個憑據吶,OAuth2定義了四種許可類型以及用于定義其他類型的可擴展性機制:
注意:以下4種授權許可是對上述(4. OAuth2的授權流程)中的ABDE四個階段的展開。
5.1 Authorization Code
這是OAuth2最常用的一種授權許可類型,比如QQ,微博,Facebook和豆瓣等等。要求Client具有可公開訪問的Server服務器來接受Authorization Code,具體的流程如下:
上圖ABCDE這5個步驟,既是完整的獲取訪問令牌的一個過程,其中引入了一些其他的概念,比如客戶端標識,刷新令牌等和重定向URL等概念,后續會在6. OAuth2附屬概念和流程介紹。
- (A)Client使用瀏覽器(用戶代理)訪問Authorization server。也就是用瀏覽器訪問一個URL,這個URL是Authorization server提供的,訪問的收Client需要提供(客戶端標識,請求范圍,本地狀態和重定向URL)這些參數。
- (B)Authorization server驗證Client在(A)中傳遞的參數信息,如果無誤則提供一個頁面供Resource owner登陸,登陸成功后選擇Client可以訪問Resource server的哪些資源以及讀寫權限。
- (C)在(B)無誤后返回一個授權碼(Authorization Code)給Client。
- (D)Client拿著(C)中獲得的授權碼(Authorization Code)和(客戶端標識、重定向URL等信息)作為參數,請求Authorization server提供的獲取訪問令牌的URL。
- (E)Authorization server返回訪問令牌和可選的刷新令牌以及令牌有效時間等信息給Client。
5.1.1 Authorization Request
對應步驟(A),客戶端提供以下參數請求Authorization Server:
比如以下示例:
GET /authorize?response_type=code&client_id=1&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2&scope=user,photo HTTP/1.1 Host: server.example.com5.1.2 Authorization Response
對應步驟(C),Authorization Server會返回如下信息:
比如示例如下:
HTTP/1.1 302 Found Location: https://client.example.com/oauth2?code=SplxlOBeZQQYbYS6WxSbIA&state=xyzLocation頭部信息指向步驟(A)提供的redirect_uri地址,同時攜帶code信息和state信息給client,這樣瀏覽器在重定向的時候就會已GET的方式訪問Client提供的redirect_uri,同時Client接收到code信息和state信息。下一步就可以請求access_token了。
5.1.3 Access Token Request
對應步驟(D),客戶端提供以下參數請求Authorization Server:
比如以下示例:
POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencodedgrant_type=authorization_code&code=123&client_id=1&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth25.1.4 Access Token Response
對應步驟(E),Authorization Server會返回如下典型的信息:
比如以下示例:
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8{"access_token":"2YotnFZFEjr1zCsicMWpAA","token_type":"example","expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value" }5.2 Implicit
這個是Authorization Code的簡化版本。其中省略掉了頒發授權碼(Authorization Code)給客戶端的過程,而是直接返回訪問令牌和可選的刷新令牌。其適用于沒有Server服務器來接受處理Authorization Code的第三方應用,其流程如下:
其步驟就不做詳細介紹了,相信大家都能理解。和Authorzation Code類型下重要的區分就是省略了Authorization Response和Access Token Request。而是直接由Authorization Request返回Access Token Response信息,具體如下。
5.2.1 Authorization Request
客戶端提供以下參數請求Authorization Server:
重點區別在于response_type為“token”,而不再是“code”,redirect_uri也變為了可選參數。
比如以下示例:
GET /authorize?response_type=token&client_id=1&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2&scope=user,photo HTTP/1.1 Host: server.example.com5.2.2 Access Token Response
Authorization Server會返回如下典型的信息:
比如以下示:
HTTP/1.1 302 Found Location: http://client.example.com/oauth2#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&expires_in=3600注意其和Authorization Code的最大區別在于它是把token信息放在了url的hash部分(#后面),而不是作為參數(?后面)。這樣瀏覽器在訪問重定向的Location指定的url時,就不會把這些數據發送到服務器。而Client可以通過讀取Location頭信息中獲取到access_token信息。
5.3 Resource Owner Password Credentials Grant
看看流程圖:
這種模式再一步簡化,和Authorzation Code類型下重要的區分就是省略了Authorization Request和Authorization Response。而是Client直接使用Resource owner提供的username和password來直接請求access_token(直接發起Access Token Request然后返回Access Token Response信息)。這種模式一般適用于Resource server高度信任第三方Client的情況下。
客戶端提供以下參數請求Authorization Server:
比如以下示例:
POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencodedgrant_type=password&username=blackheart&password=1234Access Token Response和Authorization Code一致,就不列出來了。
5.4 Client Credentials Grant
這種類型就更簡化了,Client直接已自己的名義而不是Resource owner的名義去要求訪問Resource server的一些受保護資源。
客戶端提供以下參數請求Authorization Server:
比如以下示例:
POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencodedgrant_type=client_credentialsAccess Token Response和Authorization Code一致,就不列出來了。
以筆者以前做公共號開發的經驗,它提供由這類的OAuth2許可類型,這個場景下得到的access_token的所屬人是公眾號的,可以用此access_token來獲取所有已關注的用戶的信息,而不局限于特定的某一個用戶,正是Client Credentials Grant這種類型的許可的用武之地,案例文檔地址在文章最后面。
6 OAuth2刷新令牌
在上述得到訪問令牌(access_token)時,一般會提供一個過期時間和刷新令牌。以便在訪問令牌過期失效的時候可以由客戶端自動獲取新的訪問令牌,而不是讓用戶再次登陸授權。那么問題來了,是否可以把過期時間設置的無限大呢,答案是可以的,筆者記得Pocket的OAuth2拿到的訪問令牌就是無限期的,好像豆瓣的也是。如下是刷新令牌的收客戶端需要提供給Authorization Server的參數:
比如以下示例:
POST /token HTTP/1.1Host: server.example.comgrant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA響應信息和5.1.4 Access Token Response保持一致。
7 Token傳遞方式
在第三方Client拿到access_token后,如何發送給Resouce Server這個問題并沒有在RFC6729種定義,而是作為一個單獨的RFC6750來獨立定義了。這里做以下簡單的介紹,主要有三種方式如下:
7.1 URI Query Parameter
這種使用途徑應該是最常見的一種方式,非常簡單,比如:
GET /resource?access_token=mF_9.B5f-4.1JqM HTTP/1.1
Host: server.example.com
在我們請求受保護的資源的Url后面追加一個access_token的參數即可。另外還有一點要求,就是Client需要設置以下Request Header的Cache-Control:no-store,用來阻止access_token不會被Web中間件給log下來,屬于安全防護方面的一個考慮。
7.2 Authorization Request Header Field
因為在HTTP應用層協議中,專門有定義一個授權使用的Request Header,所以也可以使用這種方式:
GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
其中"Bearer "是固定的在access_token前面的頭部信息。
7.3 Form-Encoded Body Parameter
使用Request Body這種方式,有一個額外的要求,就是Request Header的"Content-Type"必須是固定的“application/x-www-form-urlencoded”,此外還有一個限制就是不可以使用GET訪問,這個好理解,畢竟GET請求是不能攜帶Request Body的。
POST /resource HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
access_token=mF_9.B5f-4.1JqM
8 OAuth2的安全問題
在OAuth2早期的時候爆發過不少相關的安全方面的漏洞,其實仔細分析后會發現大都都是沒有嚴格遵循OAuth2的安全相關的指導造成的,相關的漏洞事件百度以下就有了。
其實OAuth2在設計之初是已經做了很多安全方面的考慮,并且在RFC6749中加入了一些安全方面的規范指導。比如
安全無小事,這方面是要靠各方面(開放平臺,第三方開發者)共同防范的。如QQ互聯的OAuth2 API中,state參數是強制必選的參數,授權接口是基于HTTPS的加密通道等;同時作為第三方開發者在使用消費這些服務的時候也應該遵循其相關的安全規范。
9 總結 & 參考 & 案例
OAuth2是一種授權標準框架,用來解決的是第三方服務在無需用戶提供賬號密度的情況下訪問用戶的私有資源的一套流程規范。與其配套的還有其他相關的規范,都可以到https://oauth.net/2/去延伸閱讀和了解。
相關參考:
https://oauth.net/2/
https://www.oauth.com/
https://aaronparecki.com/oauth-2-simplified/
RFC6749 : The OAuth 2.0 Authorization Framework
RFC6749中文版(https://github.com/jeansfish/RFC6749.zh-cn)
RFC6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage.
RFC6819 - OAuth 2.0 Threat Model and Security Considerations.
OAuth2案例:
豆瓣OAuth2 API(Authorization Code)
QQ OAuth2 API(Authorization Code)
豆瓣OAuth2 API(Implicit )
QQ OAuth2 API(Implicit)
微信公眾號獲取access_token(Client Credentials Grant)。
至于Resource Owner Password Credentials Grant這種類型的許可方式,由于其適用常見,平時作為第三方開發者的開發工作中,沒有遇到此類的案例。其適用場景在于第三方應用和Resoure server屬于同一方這樣高度可信的環境下。
作者:Blackheart 出處:http://linianhui.cnblogs.com 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。總結
以上是生活随笔為你收集整理的[认证授权] 1.OAuth2授权的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原创经验:微信小程序开发总结
- 下一篇: 微信小程序正式上线 可置于聊天窗口顶部