經過上一篇.Net Core官方的 JWT 受權驗證學習到了JWT的受權。能夠發現一個問題,就是若是每一個接口可使用的角色都是寫死的,這樣若是有所修改會很是麻煩,雖然用policy能夠必定程度上緩解,可是仍是不能根治。html
因此,就須要動態的設置接口與權限,由咱們本身來處理。數據庫
咱們先建立一個類 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 判斷接口和角色的關係,從而實現了動態設置接口和權限的要求。async
我這裏的代碼比較的簡陋,最低限度的實現,能夠本身根據需求完善。也能夠看下面的參考文章。ide
參考文章:post