通過上一篇.Net Core官方的 JWT 授權驗證學習到了JWT的授權。可以發現一個問題,就是如果每個介面可以使用的角色都是寫死的,這樣如果有所修改會非常麻煩,雖然用policy可以一定程度上緩解,但是還是不能根治。
所以,就需要動態的設定介面與許可權,由我們自己來處理。
我們先建立一個類 PermissionRequirement 繼承介面 IAuthorizationRequirement,這個類是介面與角色的關係類,裡面的欄位可以按自己的需要新增。
public class PermissionRequirement : IAuthorizationRequirement { public string Url { get; set; } public List<string> Roles { get; set; } }
之後建立一個處理類 PermissionHandler 繼承 AuthorizationHandler 類,來處理請求中介面和角色許可權的關係。
public class PermissionHandler : AuthorizationHandler<PermissionRequirement> { protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) { //模擬從資料庫或者快取中取出的訪問url的許可權資料 var roles = new List<PermissionRequirement>(); roles.Add(new PermissionRequirement() { Url = "weatherforecast", Roles = new List<string>() { "system" } }); //JWT的token中的宣告等資訊都會自動解析在context中 var resource = ((Microsoft.AspNetCore.Routing.RouteEndpoint)context.Resource).RoutePattern; foreach(var t in context.User.Identities) { foreach(var claim in t.Claims) { //通過Type可以判斷宣告的型別,這裡處理role的宣告獲取角色資訊 if(claim.Type == ClaimTypes.Role) { if(roles.Exists(x => x.Roles.Exists(role => role == claim.Value) && x.Url == resource.RawText.ToLower())) { context.Succeed(requirement); return; } } } } context.Fail(); return; } }
在 Startup 類中其他都不變,只需要新增在 ConfigureServices 方法中新增上如下程式碼即可,通過以來注入 PermissionHandler 類來替換成我們的處理類。
services.AddAuthorization(option => { //option.AddPolicy("adminOrSystem", policy => policy.RequireRole("admin", "system")); option.AddPolicy("Permission", policy => policy.AddRequirements(permissionRequirement)); }); services.AddSingleton<IAuthorizationHandler, PermissionHandler>(); // 將授權必要類注入生命週期內 services.AddSingleton(permissionRequirement);
最後只需要在介面或控制器上新增 [Authorize(Policy = "Permission")] 就可以啦,只要有該特性的介面訪問都會走我們的處理類 PermissionHandler 判斷介面和角色的關係,從而實現了動態設定介面和許可權的要求。
我這裡的程式碼比較的簡陋,最低限度的實現,可以自己根據需求完善。也可以看下面的參考文章。
參考文章:
ASP.NET Core 使用 JWT 自定義角色/策略授權需要實現的介面
從壹開始前後端分離[.NetCore] 37 ║JWT完美實現許可權與介面的動態分配