ABP vnext 以“或”的方式验证多个 Authorize

在业务开发做权限管理的时候,会遇到同一个Service方法,会有多个授权的情况,这时候就要添加多个AuthorizeAttribute,类似下面这样:

       /// <summary>
        /// 获取详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Authorize(Permissions.Edit)]
        [Authorize(Permissions.View)]
        public async Task<Result> Get(Guid id)
        {
           //.....
        }

在abp vnext框架中,进行权限校验时,是以且的方式进行,即用户必须同时AuthorizeAttribute的权限才能通过校验,否则就就无权限,返回403状态码。

在博客园找到一篇文章 《abp 以或的方式验证多个 AuthorizeAttribute》,按他的方法,发现只有在使用controller再调用Service层的方法,并且AuthorizeAttribute写在Service层方法上时,才会触发该方法;如果使用自动api的方式,依然是403错误;

通过查看abp源码,看AddAlwaysAllowAuthorization 的实现方法后,发现权限校验入口是IAuthorizationService接口中下面这个方法,那么只要对这个方法进行调整就可以实现了。

 Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object? resource, IEnumerable<IAuthorizationRequirement> requirements)

abp vnext 中,该接口注入的是AbpAuthorizationService这个类,则继承该类,重写AuthorizeAsync方法,将参数requirements中,属于权限策略的部分提取出来。先用原来的方法,校验除权限策略外的其他需求规则,校验不通过,则直接返回,无需再校验权限;否则再校验权限策略,如果校验不通过,则比较不通过的数量和权限策略的数量,如果小于,则表示有部分策略通过了校验,那么改写校验结果即可。如此,便实现了以“或”的方法验证多个Authorize;

具体实现代码如下:

/// <summary>
    /// 改写鉴权方法,实现多个Authorize特性,以“或”的方式进行鉴权
    /// </summary>
    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IAuthorizationService), typeof(IAbpAuthorizationService))]

    public class MyAuthorizationService : AbpAuthorizationService, ITransientDependency
    {

        public MyAuthorizationService(IAuthorizationPolicyProvider policyProvider, IAuthorizationHandlerProvider handlers, ILogger<DefaultAuthorizationService> logger, IAuthorizationHandlerContextFactory contextFactory, IAuthorizationEvaluator evaluator, IOptions<AuthorizationOptions> options, ICurrentPrincipalAccessor currentPrincipalAccessor, IServiceProvider serviceProvider)
            : base(policyProvider, handlers, logger, contextFactory, evaluator, options, currentPrincipalAccessor, serviceProvider)
        {
        }

        /// <summary>
        /// 重写授权方法,将策略从需求规则中拆分出来,单独鉴权
        /// </summary>
        /// <param name="user"></param>
        /// <param name="resource"></param>
        /// <param name="requirements"></param>
        /// <returns></returns>
        public override async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object? resource, IEnumerable<IAuthorizationRequirement> requirements)
        {
            //如果权限策略为空,则直接返回成功
            if (requirements.Count() == 0)
            {
                return AuthorizationResult.Success();
            }
            //权限策略需求规则
            var permissionRequirements = requirements.Where(p => p.ToString()!.StartsWith("PermissionRequirement:")).ToList();

            if (permissionRequirements.Count > 0)
            {
                //从需求规则中剔除权限策略
                requirements = requirements.Where(p => !permissionRequirements.Any(q => q.Equals(p))).ToList();
            }

            //校验除权限策略外的其他需求规则
            if (requirements.Count() > 0)
            {
                var result = await base.AuthorizeAsync(user, resource, requirements);
                //如果校验失败,则直接返回,无需再校验权限规则
                if (!result.Succeeded)
                {
                    return result;
                }
            }

            //校验权限策略规则 
            if (permissionRequirements.Count > 0)
            {
                var result = await base.AuthorizeAsync(user, resource, permissionRequirements);
                //校验不通过,则检查是否全部策略都不通过,如果不是,则认为通过校验,改写校验结果 
                if (!result.Succeeded && result.Failure!.FailedRequirements.Count() < permissionRequirements.Count)
                {
                    result = AuthorizationResult.Success();
                }
                return result;
            }
            return AuthorizationResult.Success();
        }
    }

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值