1. 程式人生 > >跟我一起學.NetCore之熟悉的介面許可權驗證不能少(Jwt)

跟我一起學.NetCore之熟悉的介面許可權驗證不能少(Jwt)

**前言** 許可權管控對於一個系統來說是非常重要的,最熟悉不過的是選單許可權和資料許可權,上一節通過Jwt實現了認證,接下來用它實現介面許可權的驗證,為什麼不是選單許可權呢?對於前後端分離而言,稱其為介面許可權感覺比較符合場景(我是這麼理解的);資料許可權牽涉到具體業務,這裡就不說啦! **正文** 對於一些比較簡單的系統,訪問角色可能只有固定的幾種,比如一些產品管理系統,通常只有管理員、維護員、使用者三種許可權,管理員擁有整個系統的許可權,維護員只能訪問產品維護相關頁面和操作,使用者只能訪問產品的一些資訊,如果類似這種情況,可以直接指定角色的方式進行許可權管控,如下: 案例程式碼直接使用上一節的專案,借用上次認證那塊程式碼(偷懶太明顯~),如果沒看上一篇的小夥伴,去瞅瞅認證那塊內容([跟我一起學.NetCore之WebApi介面裸奔有風險(Jwt)](http://mp.weixin.qq.com/s?__biz=MzU1MzYwMjQ5MQ==&mid=2247484105&idx=1&sn=9322333e9fc39a0a0daf2c4901cf1efd&chksm=fbf11e1dcc86970be6a815b946d43b0f6753f89d3fb6b447b21a1e10373be44cbc59e0ebfe15&scene=21#wechat_redirect)),隨便敲敲程式碼,這節要用(別說我,我是有苦衷的,想讓小夥伴多擼程式碼~~~);如果只是想熟悉知識點,也可以繼續往下看的,不廢話,直接開始: ![img](https://i.loli.net/2020/10/12/gAH1qXPr3YMVlJQ.png) 注:[Authorize]加在控制器上時,該控制器下所有的介面都受保護; 為了方便測試,如上圖所示,增加一個產品控制器,針對不同人員模擬了三個介面,因為介面受到保護,只能通過獲取到的Token才能正常訪問,這裡就不截圖演示了。Token呼叫User中的Login介面獲取,詳細請參考([跟我一起學.NetCore之WebApi介面裸奔有風險(Jwt)](http://mp.weixin.qq.com/s?__biz=MzU1MzYwMjQ5MQ==&mid=2247484105&idx=1&sn=9322333e9fc39a0a0daf2c4901cf1efd&chksm=fbf11e1dcc86970be6a815b946d43b0f6753f89d3fb6b447b21a1e10373be44cbc59e0ebfe15&scene=21#wechat_redirect))。哎呀,還是上個生成Token的程式碼圖: ![img](https://i.loli.net/2020/10/12/JLltE9zipRrCg8s.png) 下面將三個介面指定為不同角色訪問,然後執行訪問如下: ![img](https://i.loli.net/2020/10/12/Lt5pWkf3sE29qwQ.png) ![img](data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==) 通過執行測試可知,當增加了對應角色要求之後,儘快Token驗證正確,也不能正常呼叫介面,返回403禁止訪問。已經為介面指定了角色,那要如何才能正常呼叫呢?其實只要在生成Token的時候指定對應角色即可正常訪問對應角色的介面,如下程式碼優化: ![img](https://i.loli.net/2020/10/12/BuZScAwLhpbGfQJ.png) ![img](data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==) 如上執行所示,在生成Token時指定了角色為Admin,則這個Token只能訪問指定角色為Admin的介面,其他介面是不能訪問的。如需要訪問其他介面,同樣需要在生成Token的時候新增對應的角色,如下: ![img](https://i.loli.net/2020/10/12/GkZydKxi4laDNp3.png) 執行效果這裡就不截圖演示了,小夥伴們自己試試。 看到這,小夥伴們肯定會問,管理員角色肯定是所有介面都能訪問,拿到了Token接下來該咋辦,每個介面都加管理員角色對應的特性嗎?對於多個角色訪問同一個介面的情況,一般會為授權定義策略來實現,如下: ![img](https://i.loli.net/2020/10/12/JL5zXo1pba7sIPR.png) 執行效果如下: ![img](https://i.loli.net/2020/10/12/9lLR76mTnisH5hw.png) 小注意點: - 多個角色或運算:多個角色只要有其中一個就可以訪問; - 多個角色且運算:同時得有多個角色才能訪問介面; ![img](https://i.loli.net/2020/10/12/MK87TORp9BnswNr.png) 到這,相信小夥伴已經忍不住要問:不管是角色還是策略的方式,角色都寫死了,如果角色動態分配許可權咋搞? 是的,上面的方式只適合對許可權管控比較簡單的專案,絕大數的專案許可權肯定是動態分配的,即根據需求,可以針對使用者進行訪問許可權配置,所以接下來就說說這塊咋搞。 這次增加的程式碼稍微有點多,程式碼都有註釋,另外跟著我標註的步驟走,絕對No Problem: ![img](https://i.loli.net/2020/10/12/qFxNo49PDdH2aJm.png) ![img](https://i.loli.net/2020/10/12/oplnx5MZ4BCrOLf.png) ![img](https://i.loli.net/2020/10/12/18YPSNBsfVXnlyJ.png) 通過以上步驟就完成動態許可權的驗證了,是不是很給力,這裡需要注意一下幾個點: - 後續用到IHttpContextAccessor需要進行註冊; ![img](https://i.loli.net/2020/10/12/CpOHo7c4qTk8Qhu.png) - 使用者ID在登入的時候要放入Payload中,後續許可權驗證時要用; ![img](https://i.loli.net/2020/10/12/hy3jxs5tp6lzXSO.png) - API中使用的策略名稱要和定義的一致; ![img](https://i.loli.net/2020/10/12/PfzmZoxlM4Wur8v.png) 以上案例演示中,在登入的時候模擬許可權資料存入記憶體,對於一些使用者資料不大的專案,這種方式還不錯,但是對於使用者數量比較大或者分散式部署的專案,建議將許可權資料存入Redis等快取資料庫中,存取統一的同時也能減少對資料庫的訪問壓力,總不能每次請求過來都從資料庫中獲取許可權資料進行校驗。 小知識點: - 通過獲取使用者時,訪問的介面必須要有Authorize特性,否則只能通過自己解析Token獲取; - 如果在統一受保護的控制器中,有個別介面不需要許可權驗證,可以為其標註AllowAnonymous特性即可; 校驗許可權邏輯的完整程式碼如下: ```c# using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace SwaggerDemo.Permission { /// /// 許可權處理的關鍵類 /// public class PermissionHandler : Authorizatio