開放受權(OAuth)是一個開放標準,容許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯繫人列表),而無需將用戶名和密碼提供給第三方應用。 —— 維基百科
嚴格來講,OAuth2 不是一個標準協議,而是一個安全的受權框架。其詳細描述系統中不一樣角色,用戶,服務前端應用(如 API )以及客戶端(如網站或APP)之間如何實現相互認證。html
當前 OAuth 協議版本是 OAuth2.0,須要注意的是,OAuth2.0 並不向下兼容 OAuth1.0。前端
在生活中,比較常見的 OAuth2 的使用場景是受權登陸,而且也普遍應用於 web、桌面應用和移動 APP 的第三方服務提供受權登陸驗證機制,以實現不一樣應用直接數據訪問的權限。git
在 OAuth2 標準中定義瞭如下四種角色:github
表明受權客戶端訪問自己資源信息的用戶(User);web
表明意圖訪問受限資源的第三方應用。後端
表明託管了受保護的用戶帳號信息的服務器,它與認證服務器,能夠是同一臺服務器,也能夠是不一樣的服務器;瀏覽器
表明驗證用戶身份而後爲客戶端派發資源訪問令牌的服務器,即服務提供商專門用來處理認證的服務器;安全
(配圖來自阮一峯大佬)服務器
大體流程歸納就是:微信
用戶打開客戶端之後,客戶端要求用戶給予受權。
用戶贊成給予客戶端受權。
客戶端向受權服務器發送它本身的客戶端身份標識和上一步中得到的受權(authorization grant),向認證服務器申請令牌。
認證服務器對客戶端進行認證之後,確認無誤,贊成發放令牌(access token),受權階段至此所有結束。
客戶端使用令牌,向資源服務器申請獲取資源。
資源服務器確認令牌無誤,贊成向客戶端開放資源。
理解完上面整個流程之後,咱們再看看下面這張圖,能更加清晰理解 OAuth2 的整個運行流程:
(配圖來自公衆號前端修仙之路)
從整個流程能夠看出,在 B 步驟最爲關鍵,即須要獲取到用戶對客戶端的受權(如咱們在微信掃碼登陸時,點擊「肯定」按鈕的步驟)。
有了這個受權之後,客戶端才能拿到令牌,進而憑令牌向資源服務器獲取資源。
另外,微信登陸的實現流程也相似:
(配圖來自微信官方文檔)
其總體流程爲:
code
參數;code
參數加上 AppID
和 AppSecret
等,經過 API 換取 access_token
;access_token
進行接口調用,獲取用戶基本數據資源或幫助用戶實現基本操做。適合快速開發實施,代碼量少,API須要被不一樣APP使用,且每一個APP使用方式也不一樣的狀況。
學習和理解的成本比較大,而且 OAuth2 不是一個嚴格的標準協議,在實施過程當中更容易出錯。
經過前面描述,能夠知道OAuth 的核心就是向第三方應用頒發令牌。
OAuth 2.0 規定了四種得到令牌的流程。你能夠選擇最適合本身的那一種,向第三方應用頒發令牌。即如下四種受權方式:
注意:
無論哪種受權方式,第三方應用申請令牌以前,都必須先到系統備案,說明本身的身份,而後會拿到兩個身份識別碼:客戶端 ID(client ID)和客戶端密鑰(client secret)。
這是爲了防止令牌被濫用,沒有備案過的第三方應用,是不會拿到令牌的。
即第三方應用先申請一個受權碼,而後再用該碼獲取令牌。
適用於有後端的 Web 應用,受權碼經過前端傳送,令牌則是儲存在後端,並且全部與資源服務器的通訊都在後端完成。這樣的先後端分離,能夠避免令牌泄漏。
這種方式也是最經常使用的流程,安全性最高。
(配圖來自阮一峯大佬)
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
參數表示要求的受權範圍(這裏是只讀);
redirect_uri
參數指定的網址,就像下面這樣:https://a.com/callback?code=AUTHORIZATION_CODE
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
參數是令牌頒發後的回調網址;
redirect_uri
指定的網址,發送包含令牌 access_token
字段的JSON數據,流程完畢。即隱藏受權碼步驟,直接向前端發放令牌,也稱受權碼隱藏式。
(配圖來自阮一峯大佬)
https://b.com/oauth/authorize? response_type=token& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read
response_type
參數爲 token
,表示要求直接返回令牌。
當用戶贊成受權後,會跳轉到 redirect_uri
參數指定的重定向地址,並將令牌做爲 URL
參數傳遞給 A 網站。
https://a.com/callback#token=ACCESS_TOKEN
token
參數就是令牌,A 網站所以直接在前端拿到令牌。
注意:
這裏的令牌位置是 URL
錨點(即 #
號),而不是查詢字符串,這是由於錨點不會發到服務器,避免泄露令牌的風險。
適用場景:
因爲直接傳遞令牌不安全,所以經常適用在對安全要求不高的場景,而且令牌有效期很是短,例如會話期間(session)有效,關閉瀏覽器便失效。
即:對於信任的應用,能夠攜帶約定的用戶名和密碼進行令牌申請。
https://oauth.b.com/token? grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID
grant_type
參數是受權方式,這裏的 password
表示"密碼式";username
和 password
是 B 的用戶名和密碼。
適用場景:
風險較大,通常適用在對應用高度信任的狀況。
即:給出憑證讓對方確認並提供令牌。
https://oauth.b.com/token? grant_type=client_credentials& client_id=CLIENT_ID& client_secret=CLIENT_SECRET
grant_type
參數等於 client_credentials
表示採用憑證式;client_id
和 client_secret
用來讓 B 確認 A 的身份。
這種方式給出的令牌,是針對第三方應用的,而不是針對用戶的,即有可能多個用戶共享同一個令牌。
適用場景:
經過命令行請求令牌。
當網站獲取到令牌之後,接下來每一個 API 請求都須要帶上令牌,其作法是在請求的頭信息中,將令牌添加 Authorization
字段中。
當令牌有效期到了,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 網站驗證經過之後,就會頒發新的令牌。
本文首發在 pingan8787我的博客,如需轉載請聯繫本人。
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推薦 | https://github.com/pingan8787... |
ES小冊 | js.pingan8787.com |