/*对比*/

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,批量导入接口说明,然后菜单维护只要选择这些接口就好,不过制作菜单还是很麻烦,需要对按钮操作还需要指定上级,若博友们在实际生产中有更好的实现方式,恳请留言下,万分感谢!!

剧终!!!

posted @ 2020-12-07 16:27  蔡风剑  阅读(576)  评论(0编辑  收藏  举报