一 Oauth2這個是爲了方便安全的用戶(第三方)登錄用的。
一開始聽見oauth2這個詞肯定是很懵的。這是啥,鑑權用的?認證用的?授權用的?跟shiro(java)是一個東西嗎?
其實oauth就是一個流程。我們根據這個流程的要求寫代碼、
oauth有一個授權服務器。是作爲用戶的認證用的。對於服務端來說只需實現一個oauth的授權服務器。對於用戶來說(調用授權認證的研發)只需根據流程發請求就可以了。
二 Oauth 有四種實體。 下面以用QQ登陸微博爲例。
資源所有者(resource owner) 我們(普通用戶)
資源服務器(resource server) QQ的後臺服務器(獲取賬號,暱稱,頭像等)。
應用程序(client) 微博這個平臺
授權服務器(Authorization Server) 認證QQ & 授權用的。
三 oauth有四種方式。 目的是不把密碼暴露給第三方。(即不把QQ賬號密碼暴露給微博)
1.授權碼 authorization code 也是安全等級最高的一版。 支持refresh token 一般都用這個,微博QQ登錄就是這種方式。
2.密碼 password credentials 支持refresh token 這種安全等級低。誰知道client會不會偷摸存你密碼不。一般內部使用
3.簡化模式 implicit 不支持refresh token 這種沒有獲取code的步驟。請求就給token、 沒get到這個的優勢
4.客戶端模式 client credentials 不支持refresh token 這種是被信任的內部client使用。一般內部平臺間使用
注: client_id client_secret 是用來oauth server鑑別client用的。
下面詳細說明一下各個方式。簡化模式就不說了。
四 客戶端模式。(grant_type = client_credentials)
使用場景: 一般是內部系統之間的API調用。兩個平臺之間調用。調用者是以平臺爲單位。而不是以用戶爲單位。
舉個簡單例子:A平臺調用B平臺的刪除API 爲了防止B 平臺的刪除API不被隨便調用(即拿到cookie就在postman等工具一頓調),使用客戶端授權的方式來處理。爲了保護B平臺資源而使用。
代碼邏輯過程如下
1.A系統根據B系統提供好的client_id client_secret 向B平臺獲取access_token的接口發請求。
默認的接口是/oauth/token 這個要看實現oauth的server是咋定義的。
(client_id client_secret這兩個值存在storage裏。可能在數據庫中可能在緩存中,需要放哪就放哪)
如下圖所示,調用B平臺的oauth server 獲取access_token的接口來獲取access_token
2.通過access_token獲取資源
如下圖所示,access_token 可以通過下面這種放到 x-www-form-urlencoded 的方式跟參數一起傳過去。認證並獲取資源。 也可以放到header中。完全取決於你的server是怎麼寫的代碼。馬賽克的是接口參數,跟文章沒啥用。
以上:對於客戶端模式的總結就是。一共兩次請求,第一次獲取access_token 第二次獲取資源。
五 密碼模式。(grant_type = password)
使用場景 內部系統之間調用。但是要提供密碼。(A平臺向B平臺請求用戶在B平臺的數據) 這個不要在公網使用。密碼暴露給第三方了。這個就是以用戶爲單位的了。
與客戶端模式的區別在於客戶端模式將平臺和用戶(client & resource owner )結合成了一個。 而密碼模式是將client 和 resource owner 拆開了。
這個例子是基於springboot的。例子代碼來源:https://blog.csdn.net/LightOfMiracle/article/details/79151074
"我"來模擬用戶輸入 "我"將密碼給postman 用postman模擬client springboot項目模擬資源服務器&授權服務器。
注:下圖中header有一個屬性 Authorization 對應 Basic dGVzdDoxMjM0NTY= 後面這個串是 client_id:client_secret 用base64編碼的結果。 這個是springboot security整合 oauth的默認方式。(是可以改的)
1、"我"將密碼給postman。 postman向oauth server發起請求來獲取access_token
2、我用access_token獲取資源。注意這個access_token要寫在header的Authorization中 對應 token_type access_token (這個是springboot整合oauth的默認方式。)
實際上是 /oauth/token 就是往springboot中註冊一個對象來定時存一個access_token等信息。 然後我們調用需要鑑權的接口就是根據 access_token解析對應的數據。
以上:對於密碼模式的總結就是。一共兩次請求,第一次獲取access_token第二次獲取資源。密碼模式就是將調用方設定爲普通的資源擁有者 resource owner
六 授權碼模式。(grant_type = authorization_code)
使用場景:可以在公網中。也是最常見的。也是最重要的。
1.還是以微博爲例。 登錄選擇以QQ登錄、會轉到如下這個頁面。
拆一下。可以看到 client_id=101019034這個客戶端id這個是標識微博這個平臺用的。
response_type = code 這個是必須這麼寫。
scope可選項。 標識範圍
redirect_uri 請求返回要重定向的地址。
state 這個是一個隨便寫的值。標識用戶的本次請求不會被csrf 篡改。如果有這個參數,會返回這個參數。
2.認證並同意授權。這個就是在上面這個頁面輸入QQ賬號密碼在QQ的服務器進行校驗。這個是安全的。上面這個鏈接是QQ方提供的。 校驗成功後會生成一個code值。如果請求帶state會原封不動的將這個值返回回去。
步驟1的response 大概這樣 https://xxxxweibo.com?code=asdad123esd&state=asdqw
3.取獲取access_token 這個是調用大概這樣的獲取token的接口 https://graph.qq.com/oauth2.0/token 參數如下。
返回結果如下
{
"access_token": "a3a961a1-a74d-45ca-9683-ca683efeb144",
"token_type": "bearer",
"refresh_token": "903e6410-d381-4868-bde6-4a76f4112156",
"expires_in": 9999,
"scope": "read write"
}
4.通過access_token獲取資源。
以上:對於授權碼模式的總結就是。一共三次請求,第一次獲取code,第二次獲取access_token 第三次獲取資源。
一個關於什麼時候使用什麼授權方式的圖譜
七 Golang & Oauth2
授權服務器可以使用 gopkg.in/oauth2.v3 這個包來搭建。
選圖框中的兩個可以打開兩個終端 分別 go run client.go go run server.go 運行訪問localhost:9094 可以註冊access_token
訪問資源爲 localhost:9094/try
具體可以仿照example 包中的例子來自己重寫、
參考:
https://alexbilbie.com/guide-to-oauth-2-grants/
https://blog.csdn.net/LightOfMiracle/article/details/79151074