本文收錄在個人部落格:www.chengxy-nds.top,技術資源共享,一起進步
上週我的自研開源專案開始破土動工了,《開源專案邁出第一步,10 選 1?頁面模板成了第一個絆腳石
》 ,密謀很久才付諸行動,做這個的初衷就是不想讓自己太安穩,技術這條路不進步就等於後退,必須要逼著自己學習。
專案偏向於技術實踐,因此不會做太多的業務堆砌,業務程式碼還是在公司學習比較好。現在正在做技術的選型與儲備,像比較主流的,專案前後端分離
、微服務
、Springboot
、Springcloud
等都會應用到專案中,其實很多技術我也不會,也是在反覆的查閱資料求證,探索的過程技術提升真的要比工作中快很多,畢竟主動與被動學習是有本質區別的。
這幾天打算先把專案的前後端分離架構搭建完成,既然是前後端分離專案就免不了做鑑權, 所以 oauth2.0
是一個我們不得不瞭解的知識點。
一、OAuth2.0 為何物
OAuth
簡單理解就是一種授權機制,它是在客戶端和資源所有者之間的授權層,用來分離兩種不同的角色。在資源所有者同意並向客戶端頒發令牌後,客戶端攜帶令牌可以訪問資源所有者的資源。
OAuth2.0
是OAuth
協議的一個版本,有2.0
版本那就有1.0
版本,有意思的是OAuth2.0
卻不向下相容OAuth1.0
,相當於廢棄了1.0
版本。
舉個小栗子解釋一下什麼是 OAuth 授權?
在家肝文章餓了定了一個外賣,外賣小哥30秒火速到達了我家樓下,奈何有門禁進不來,可以輸入密碼進入,但出於安全的考慮我並不想告訴他密碼。
此時外賣小哥看到門禁有一個高階按鈕“一鍵獲取授權
”,只要我這邊同意,他會獲取到一個有效期 2小時的令牌(token
)正常出入。
令牌(token
)和 密碼
的作用雖然相似都可以進入系統,但還有點不同。token
擁有許可權範圍,有時效性的,到期自動失效,而且無效修改。
二、OAuth2.0 授權方式
OAuth2.0
的授權簡單理解其實就是獲取令牌(token
)的過程,OAuth
協議定義了四種獲得令牌的授權方式(authorization grant
)如下:
- 授權碼(
authorization-code
) - 隱藏式(
implicit
) - 密碼式(
password
): - 客戶端憑證(
client credentials
)
但值得注意的是,不管我們使用哪一種授權方式,在三方應用申請令牌之前,都必須在系統中去申請身份唯一標識:客戶端 ID(client ID
)和 客戶端金鑰(client secret
)。這樣做可以保證 token
不被惡意使用。
下面我們會分析每種授權方式的原理,在進入正題前,先了解 OAuth2.0
授權過程中幾個重要的引數:
response_type
:code 表示要求返回授權碼,token 表示直接返回令牌client_id
:客戶端身份標識client_secret
:客戶端金鑰redirect_uri
:重定向地址scope
:表示授權的範圍,read
只讀許可權,all
讀寫許可權grant_type
:表示授權的方式,AUTHORIZATION_CODE
(授權碼)、password
(密碼)、client_credentials
(憑證式)、refresh_token
更新令牌state
:應用程式傳遞的一個隨機數,用來防止CSRF
攻擊。
1、授權碼
OAuth2.0
四種授權中授權碼方式是最為複雜,但也是安全係數最高的,比較常用的一種方式。這種方式適用於兼具前後端的Web
專案,因為有些專案只有後端或只有前端,並不適用授權碼模式。
下圖我們以用WX
登入掘金為例,詳細看一下授權碼方式的整體流程。
使用者選擇WX
登入掘金,掘金會向WX
發起授權請求,接下來 WX
詢問使用者是否同意授權(常見的彈窗授權)。response_type
為 code
要求返回授權碼,scope
參數列示本次授權範圍為只讀許可權,redirect_uri
重定向地址。
https://wx.com/oauth/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=http://juejin.im/callback&
scope=read
使用者同意授權後,WX
根據 redirect_uri
重定向並帶上授權碼。
http://juejin.im/callback?code=AUTHORIZATION_CODE
當掘金拿到授權碼(code)時,帶授權碼和密匙等引數向WX
申請令牌。grant_type
表示本次授權為授權碼方式 authorization_code
,獲取令牌要帶上客戶端密匙 client_secret
,和上一步得到的授權碼 code
。
https://wx.com/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=http://juejin.im/callback
最後 WX
收到請求後向 redirect_uri
地址傳送 JSON
資料,其中的access_token
就是令牌。
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
......
}
2、隱藏式
上邊提到有一些Web
應用是沒有後端的, 屬於純前端應用,無法用上邊的授權碼模式。令牌的申請與儲存都需要在前端完成,跳過了授權碼這一步。
前端應用直接獲取 token
,response_type
設定為 token
,要求直接返回令牌,跳過授權碼,WX
授權通過後重定向到指定 redirect_uri
。
https://wx.com/oauth/authorize?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=http://juejin.im/callback&
scope=read
3、密碼式
密碼模式比較好理解,使用者在掘金直接輸入自己的WX
使用者名稱和密碼,掘金拿著資訊直接去WX
申請令牌,請求響應的 JSON
結果中返回 token
。grant_type
為 password
表示密碼式授權。
https://wx.com/token?
grant_type=password&
username=USERNAME&
password=PASSWORD&
client_id=CLIENT_ID
這種授權方式缺點是顯而易見的,非常的危險,如果採取此方式授權,該應用一定是可以高度信任的。
4、憑證式
憑證式和密碼式很相似,主要適用於那些沒有前端的命令列應用,可以用最簡單的方式獲取令牌,在請求響應的 JSON
結果中返回 token
。
grant_type
為 client_credentials
表示憑證式授權,client_id
和 client_secret
用來識別身份。
https://wx.com/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
三、令牌的使用與更新
1、令牌怎麼用?
拿到令牌可以呼叫 WX
API 請求資料了,那令牌該怎麼用呢?
每個到達WX
的請求都必須帶上 token
,將 token
放在 http
請求頭部的一個Authorization
欄位裡。
如果使用postman
模擬請求,要在Authorization
-> Bearer Token
放入 token
,注意:低版本postman
沒有這個選項。
2、令牌過期怎麼辦?
token
是有時效性的,一旦過期就需要重新獲取,但是重走一遍授權流程,不僅麻煩而且使用者體驗也不好,那如何讓更新令牌變得優雅一點呢?
一般在頒發令牌時會一次發兩個令牌,一個令牌用來請求API
,另一個負責更新令牌 refresh_token
。grant_type
為 refresh_token
請求為更新令牌,引數 refresh_token
是用於更新令牌的令牌。
https://wx.com/oauth/token?
grant_type=refresh_token&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
refresh_token=REFRESH_TOKEN
總結
OAuth2.0
授權其實並不是很難,只不過授權流程稍顯麻煩,邏輯有些繞,OAuth2.0
它是面試經常會被問到的知識點,還是應該多瞭解一下。下一篇實戰 OAuth2.0
四種授權,敬請期待,歡迎關注哦~
原創不易,燃燒秀髮輸出內容,如果有一丟丟收穫,點個贊鼓勵一下吧!
整理了幾百本各類技術電子書,送給小夥伴們。關注公號回覆【666】自行領取。和一些小夥伴們建了一個技術交流群,一起探討技術、分享技術資料,旨在共同學習進步,如果感興趣就掃碼加入我們吧!