经过上一篇.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