NetCore自定义授权---记录
之前做MVC项目的菜单授权,都是通过Filter去校验Url是否可访问action,大体思路:
1.需要验证的controller 或action 用继承特性[AuthorizeAttribute]标记
2.用户登录获取可访问的菜单集合记录缓存
3.在特性方法中 校验 集合缓存是否有当前action,确认是否可访问。
现Core/.Net5大火(虽然学习有点晚,但是还得学习啊o(╥﹏╥)o),WebAPI的权限设置没玩过,在研究官方文档,结合博客大佬们(关注了好几个MVP)的博文,记录一个实现思路
1.采用的是自定义策略模式,原因:固定role和claim的授权对开发不够灵活,自定义策略可以自己写代码校验是否授权通过,官方文档介绍
2.实现需要的几个类和接口
1)自定义校验类需要实现 IAuthorizationRequirement ,此接口只是标记作用,然后可以自定义属性,我的实现如下
public class CustomRequirement: IAuthorizationRequirement { /// <summary> /// 全部权限集合 /// </summary> public List<RoleMenu> PowerList { get; set; } }
public class RoleMenu { /// <summary> /// 菜单路径 /// </summary> public string Url { get; set; } /// <summary> /// 角色ID /// </summary> public string RoleId { get; set; } }
2)增加处理逻辑 ,需要实现抽象接口 AuthorizationHandler<CustomRequirement> 泛型类是我们刚实现 IAuthorizationRequirement 的类,大体逻辑
public class MyAuthorHandle : AuthorizationHandler<CustomRequirement> { private readonly IHttpContextAccessor _httpContextAccessor; public MyAuthorHandle(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement) { var hasroute = requirement.PowerList.FirstOrDefault(t => t.Url.ToLower() == _httpContextAccessor.HttpContext.Request.Path.Value.ToLower()//校验路径 && context.User.Claims.FirstOrDefault(m=>m.Type==ClaimTypes.Role&&m.Value== t.RoleId)!=null//查看当前用户的Role是否被包含 ); if (hasroute != null) { //可以访问 context.Succeed(requirement); } //默认是Fail return Task.CompletedTask; } }
3)调用,需要在Starup的鉴权服务中添加以下代码
services.AddSingleton<IAuthorizationHandler, MyAuthorHandle>(); services.AddSingleton<CustomRequirement>(); services.AddAuthorization(option => { //自定义策略 option.AddPolicy("CustomPolicy", policy => { var customRequirement = new CustomRequirement() { PowerList = new List<RoleMenu>() }; //此处需要从数据库获取权限集合,并注入单例,这样就可以在权限修改后对此单例直接修改权限集合 //测试数据 customRequirement.PowerList.Add( new RoleMenu() { RoleId = "ceshi", Url = "/home/Index" } ); policy.Requirements.Add(customRequirement); }); });
4)Contoller 使用,对需要菜单校验的action或Contoller 可以添加 [Authorize(Policy = "CustomPolicy")]
此实现方式,需要维护大量接口,先有个想法,在开发阶段制定个标准特性或效仿Swagger 读取到所有接口,制作成一个SQL,批量导入接口说明,然后菜单维护只要选择这些接口就好,不过制作菜单还是很麻烦,需要对按钮操作还需要指定上级,若博友们在实际生产中有更好的实现方式,恳请留言下,万分感谢!!
剧终!!!
在后悔前 一定要先去努力尝试,加油!!!