zoukankan      html  css  js  c++  java
  • abp 以或的方式验证多个 AuthorizeAttribute

    前言

    在使用 abp 开发业务功能时,会遇到公用同一个类的情况,在给这个类配置权限时,就要添加多个 AuthorizeAttribute,类似下面这样:

        [Authorize(DcsPermissions.DocCenter.Doc.Default)]
        [Authorize(DcsPermissions.WorkingPlatform.MyDraft.Default)]
        public class DocAppService : DcsAppServiceBase, IDocAppService
        {
            // ......
        }

    但是 abp 在验证时,会以且的方式验证这两个 Policy,只要一个没有权限,则返回 403 状态码。如果想以或的方式(只要有一个有权限,那么就返回有权限)验证如何做呢?通过查看 abp 源码,我们可以新增一个 IMethodInvocationAuthorizationService 接口的实现替换掉 abp 默认的实现 MethodInvocationAuthorizationService 。这个类实现的唯一目的就是通过 AuthorizeAttribute 构造出 AuthorizationPolicy 然后使用 IAbpAuthorizationService 验证权限。下面看看我如何实现或的方式进行验证权限吧。

    实现

    代码不多,就直接看下面的代码吧

        [Dependency(ReplaceServices = true)]
        public class MyMethodInvocationAuthorizationService : IMethodInvocationAuthorizationService, ITransientDependency
        {
            private readonly IAbpAuthorizationService _abpAuthorizationService;
    
            public AutobioMethodInvocationAuthorizationService(IAbpAuthorizationService abpAuthorizationService)
            {
                this._abpAuthorizationService = abpAuthorizationService;
            }
    
            public async Task CheckAsync(MethodInvocationAuthorizationContext context)
            {
                if ( this.AllowAnonymous(context))
                {
                    return;
                }
    
                var policyNames = this.GetAuthorizationDataPolicyNames(context.Method);
                if ( policyNames.Any() )
                {
                    var isGranted = await this._abpAuthorizationService.IsGrantedAnyAsync(policyNames);
                    if ( !isGranted )
                    {
                        throw new AbpAuthorizationException(code: AbpAuthorizationErrorCodes.GivenPolicyHasNotGranted);
                    }
                }
            }
    
            protected virtual bool AllowAnonymous(MethodInvocationAuthorizationContext context)
                => context.Method.GetCustomAttributes(true).OfType<IAllowAnonymous>().Any();
    
            protected virtual string[] GetAuthorizationDataPolicyNames(MethodInfo methodInfo)
            {
                var attributes = methodInfo
                    .GetCustomAttributes(true)
                    .OfType<IAuthorizeData>();
    
                if (methodInfo.IsPublic && methodInfo.DeclaringType != null)
                {
                    attributes = attributes
                        .Union(
                            methodInfo.DeclaringType
                                .GetCustomAttributes(true)
                                .OfType<IAuthorizeData>()
                        );
                }
    
                return attributes.Where(_ => !string.IsNullOrWhiteSpace(_.Policy)).Select(_ => _.Policy).ToArray();
            }
        }

    这里面主要利益于 abp 提供了 IsGrantedAnyAsync 扩展方法。

    总结

    打算把这个想法提个 PR 给 abp 项目。整个扩展过程下来的感觉 abp 挺灵活的。abp 默认达不到的要求,几乎都可以通过扩展它来解决掉。

    这个方式目前测试下来有个问题,如果无权限,则返回的状态码是500,而非 403.

    本博客内容,如需转载请务必保留超链接。

    Contact Me:Mail此处省略好几个字...
  • 相关阅读:
    CODING x 百果园 _ 水果零售龙头迈出 DevOps 体系建设第一步
    Nocalhost 亮相 CD Foundation 国内首届 Meetup,Keith Chan 将出席致辞
    做云原生时代标准化工具,实现高效云上研发工作流
    打造数字化软件工厂 —— 一站式 DevOps 平台全景解读
    WePack —— 助力企业渐进式 DevOps 转型
    CODING Compass —— 打造行云流水般的软件工厂
    Nocalhost —— 让云原生开发回归原始而又简单
    CODING 代码资产安全系列之 —— 构建全链路安全能力,守护代码资产安全
    Nocalhost:云原生开发新体验
    使用 Nocalhost 开发 Kubernetes 中的 APISIX Ingress Controller
  • 原文地址:https://www.cnblogs.com/jRoger/p/15339300.html
Copyright © 2011-2022 走看看