如何在.netcore 上实现 Rbac 权限管理
如何在.netcore 上实现 Rbac 权限管理
1、.netcore 的权限系统
.netcore 的权限系统是将认证系统和授权系统分两步实现的
1 2 3 4 5 6 7 8 9 10 11 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... // 认证系统 app.UseAuthentication(); // 授权系统 app.UseAuthorization(); ... } |
认证系统:解决用户是谁的问题。
当用户完成 Login 操作后,用户携带的相关信息通过 Claims 直接存到了 HttpContext.User.Identity 中。
授权系统:解决该用户有没有对应的权限问题。
2、.netcore 上的自定义授权实现
可以在 controller 上加 attribute 的方式,通过实现 IAsyncAuthorizationFilter 接口获得授权执行的入口。
1 2 3 4 5 6 7 8 9 10 11 12 13 | [Authorize] public class HomeController : Controller { ... [PermissionFilter] public IActionResult Privacy() { return View(); } ... } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true , Inherited = true )] public class PermissionFilter : Attribute, IAsyncAuthorizationFilter { public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { var url = context.HttpContext.Request.Path; var authorizationService = context.HttpContext.RequestServices.GetRequiredService<IAuthorizationService>(); var authorizationResult = await authorizationService.AuthorizeAsync(context.HttpContext.User, null , new PermissionAuthorizationRequirement(url)); if (!authorizationResult.Succeeded) { context.Result = new ForbidResult(); } } } |
其中 authorizationService 是自定义的授权类,需要在 Startup 文件中的 ConfigureServices 函数中提前注册好,而 PermissionAuthorizationRequirement() 是授权类需要用到的参数类
1 2 3 4 5 6 | public void ConfigureServices(IServiceCollection services) { ... services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>(); } |
下面的代码是 PermissionAuthorizationHandler 的具体实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public class PermissionAuthorizationRequirement : IAuthorizationRequirement { public PermissionAuthorizationRequirement( string path) { Path = path; } public string Path { get ; set ; } } public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionAuthorizationRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionAuthorizationRequirement requirement) { if (context.User != null ) { if (context.User.IsInRole( "admin" )) { context.Succeed(requirement); } else { var userIdClaim = context.User.FindFirst(_ => _.Type == ClaimTypes.NameIdentifier); if (userIdClaim != null ) { //if (_userStore.CheckPermission(int.Parse(userIdClaim.Value), requirement.Path)) { context.Succeed(requirement); } } } } return Task.CompletedTask; } } |
通过在 HandleRequirementAsync 函数中,返回
1 | context.Succeed(requirement) |
表示授权通过。
3、Rbac 授权实现
通过 1和2 ,我们找到了实现自定义授权的方式,下面看看 Rbac 授权如何实现。
Rbac 是通过把 permission 列表配给 role ,然后把多个 role 分配给用户。
对于 controller 上的函数 Path ,正好就是这里的 permission,所以授权就是检测用户是否有 Path 的授权。
1 | CheckPermission( int .Parse(userIdClaim.Value), requirement.Path) |
4、参考资料
在ASP.NET Identity 2.0中使用声明(Claims)实现用户组
扩展IdentityRole和IdentityUser(Extending IdentityRole and IdentityUser)
如何创建UserManager的实例(How do i create an instance of UserManager)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步