1. 程式人生 > >IdentityServer4 之 Resource Owner Password Credentials 其實有點尷尬

IdentityServer4 之 Resource Owner Password Credentials 其實有點尷尬

### 前言 接著IdentityServer4的授權模式繼續聊,這篇來說說 Resource Owner Password Credentials授權模式,這種模式在實際應用場景中使用的並不多,只怪其太開放啦,直接在**客戶端**上拿著使用者名稱和密碼就去**授權伺服器**獲取**AccessToken**,這樣容易被**客戶端**拿著使用者名稱和密碼搞壞事;接下來就詳細說說。 ### 正文 **Resource Owner Password Credentials**授權模式與上一節說到的[客戶端憑據模式](https://mp.weixin.qq.com/s?__biz=MzU1MzYwMjQ5MQ==&mid=2247484451&idx=1&sn=52d10586571e43432e6a00f3f0877303&chksm=fbf118f7cc8691e1c9b7bf6207ccc07d26371a95c9f8faf4978625a89c5ece0c8c2e1a876af1&scene=21#wechat_redirect)不同,這是有使用者參與的,使用者就是資源擁有者;通過允許在客戶端使用使用者名稱和密碼的方式向授權伺服器獲取AccessToken,AccessToken和使用者相關,即不同的使用者獲取到的AccessToken不一樣。 ##### 術語解釋: - **Resource Owner**:資源所有者,即擁有資源的使用者; 絕大對數小夥伴都應該有自己的QQ,如果沒特殊情況,相信每一個小夥伴的QQ空間中都有自己曾經覺得很酷或很有紀念意義的照片,這裡的照片就是資源,而小夥伴就是資源所有者。 QQ伺服器就是資源伺服器。 #### Resource Owner Password Credentials 流程 ![image-20210106122921243](https://i.loli.net/2021/01/06/Q4IRVwWxhdceiKO.png) 流程簡要說明: 1. 首先使用者和客戶端需要提前在授權伺服器上備案過的,使用者沒有備案,在資源伺服器肯定就沒有對應的資源,客戶端沒有備案就不能隨意去授權伺服器獲取AccessToken; 2. 使用者在客戶端上輸入使用者名稱和密碼,並帶上備案過的客戶端憑據一起請求授權伺服器獲取AccessToken; 3. 授權伺服器驗證使用者憑據和客戶端憑據,成功之後直接返回代表該使用者的AccessToken; 4. 使用者在操作時,帶上AccessToken訪問資源伺服器; 5. 資源伺服器正常返回結果,如果沒有AccessToken是不能訪問受保護資源的; 結合流程,看看程式碼如何實現,步伐跟上哦; 這裡資源伺服器和授權伺服器就拷貝之前客戶端模式的程式碼(這樣每種模式的程式碼區分開,方便檢視),在原有基礎上修改程式碼即可; 程式碼地址:https://github.com/zyq025/IDS4Demo ##### >>在原有的授權伺服器上增加程式碼 1. 模擬在授權伺服器中備案使用者,方便測試效果,就在記憶體中模擬; ![image-20210106132546239](https://i.loli.net/2021/01/06/zTZxgj7cEefRpHk.png) 2. 備案新的客戶端,指定其授權方式; ![image-20210106133339652](https://i.loli.net/2021/01/06/c3DjWIGZ1qFlB8z.png) 3. 好啦,到這授權伺服器的修改就完成啦,用postman先測試一下; ![image-20210106135112325](https://i.loli.net/2021/01/06/18H5sg3ZDVElBwG.png) ##### >>授權伺服器修改完啦,資源伺服器不用動,那就到客戶端啦 1. 新建一個Winform窗體程式,簡單佈局安排上;並引入IdentityModel包; ![image-20210106142213334](https://i.loli.net/2021/01/06/hwfogG4szn8UaFS.png) 2. 編寫獲取AccessToken邏輯,在**GetAccessToken按鈕**點選事件中增加程式碼,如下: ![image-20210106150232248](https://i.loli.net/2021/01/06/mThRJt8HzUAuIkP.png) 3. 先啟動授權伺服器,看看access_token執行效果,如下: ![image-20210106150619514](https://i.loli.net/2021/01/06/j4zDhCUAMfydc71.png) 4. 獲取到AccessToken之後就可以訪問受保護的API啦,在**呼叫API按鈕**點選事件中進行邏輯編寫,如下: ![image-20210106151317975](https://i.loli.net/2021/01/06/DquxUeBpwaskCv4.png) 5. 授權伺服器、資源伺服器、客戶端啟動執行看效果,如下: ![image-20210106151654463](https://i.loli.net/2021/01/06/ZPIo564OtxCUvQy.png) 以上就是Resource Owner Password Credentials的使用,流程是不是很簡單。接下來聊聊這種模式的其他話題; #### Resource Owner Password Credentials的尷尬之處 在oauth2.0中如果使用這種模式,規定是不允許客戶端儲存資源所有者的使用者名稱和密碼的,但如果是第三方客戶端想搞事情,就把使用者資訊先存一把,這樣就導致間接洩露使用者資訊的風險很高(如果第三方客戶端被攻擊了),這也是這種模式在實際應用場景使用比較少的原因,如果有其他模式選擇,不建議使用此模式; 通常以下情況,可以考慮使用: - 客戶端是可高度信任的,且安全性要有保障; - 遺留應用,沒有其他好的解決方案,可以使用; #### 有使用者參與獲取的accessToken和客戶端憑據獲取到的有什麼區別 之前客戶端憑據模式的截圖: ![image-20201231154747613](https://i.loli.net/2021/01/06/6x4CgPKAfQEy1Gh.png) 資源所有者密碼模式的截圖: ![image-20210106162450204](https://i.loli.net/2021/01/06/RscLitSmA9jMy5z.png) 小夥伴肯定看出來不止多一個,但其中比較重要的就是sub這個claim,如果sub存在,呼叫API的access_token就能區分是代表使用者的,否則就是代表客戶端的。即有使用者參與獲取的acess_token是代表使用者的,每個使用者的token都不一樣。 #### refresh_token得補上 refresh_token是為了給access_token進行延長有效期而存在的,為了安全和降低風險,access_token的有效期一般設定的比較短,通常會是兩個小時(根據需要設定),當access_token失效時,常規的做法就是讓其跳轉到登入頁重新登入獲取,這樣頻繁的跳轉到登入頁,使用者體驗及其不好,為避免這種情況,需對access_token進行線上續命,即延長有效期;實現的方案各種各樣,比如有在前端定時檢測的,也有在後端做有效判斷的,但用的相對比較多還是使用refresh_token的形式,當access_token失效時,會採用refresh_token去請求新的access_token,保證使用者正常操作。 如果需要在獲取access_token的時候同時返回refresh_token,需要在授權伺服器上備案客戶端時將**AllowOfflineAccess**設定為true,如下所示: ![image-20210107100506699](https://i.loli.net/2021/01/07/JutC7pl9IkwVQNA.png) refresh_token具體使用,在後續的案例單獨說吧。 ### 總結 關於Resource Owner Password Credentials 就簡單說這麼多,主要是看看如何使用,相信小夥伴在新的專案中應該會很少用到,畢竟拿著使用者名稱和密碼直接在第三方客戶端搞事情,始終還是有風險;下一篇說說**Implicit(簡化模式)**。 一個被程式搞醜的帥小夥,關注"Code綜藝圈",跟我一起學~ ![](https://i.loli.net/2021/01/07/l7e8dBOT4acFt