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此处省略好几个字...
  • 相关阅读:
    【c#】无法修改“xxx”的返回值,因为它不是变量
    【c#】在C#中属性不可作为 ref 或 out 参数传递
    【概念】浮点数
    【概念】Winform
    【概念】数据库、服务器、N层架构、.NET、上位机、C/S和B/S、MVC、ADO.NET
    【c#】串口通信汇总
    【总线】UART、Modbus、I2C、SPI、RS232、RS485及串口通讯常用参数
    zookeeper应用场景
    Zookeeper选举(fastleaderelection算法)
    ZAB协议
  • 原文地址:https://www.cnblogs.com/jRoger/p/15339300.html
Copyright © 2011-2022 走看看