abp vnext 中多权限满足其中一个即可调用的功能实现

主要参考了微软官方 IAuthorizationPolicyProvider 的自定义授权策略的方式,创建的权限模块。(https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/iauthorizationpolicyprovider?view=aspnetcore-3.1) 

模块包含代码:

 

 AuthorizationModule.cs 代码:

using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Modularity;

namespace WebSystem.Authorization
{
    public class AuthorizationModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddSingleton<IAuthorizationPolicyProvider, WebPolicyProvider>();
            context.Services.AddSingleton<IAuthorizationHandler, WebAuthorizationHandler>();
           
        }
    }
}

IWebPermissionCheck.cs 代码:

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Text;

namespace WebSystem.Authorization
{
  public  interface IWebPermissionCheck
  {
       bool IsGranted(string[] needPermissions, ClaimsPrincipal user);
  }
}

NullWebPermissionChecker.cs 代码:

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Text;
using Volo.Abp.DependencyInjection;

namespace WebSystem.Authorization
{
    [Dependency(TryRegister = true)]
    public class NullWebPermissionChecker : IWebPermissionCheck, ITransientDependency
    {
     
        public bool IsGranted(string[] needPermissions, ClaimsPrincipal user)
        {
            return true;
        }
    }
}

WebAuthorizationHandler.cs 代码:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;

namespace WebSystem.Authorization
{
    public class WebAuthorizationHandler : AuthorizationHandler<WebRequirement>
    {
        private readonly ILogger<WebAuthorizationHandler> _logger;
        protected readonly IWebPermissionCheck _webPermissionCheck;

        public WebAuthorizationHandler(ILogger<WebAuthorizationHandler> logger, IWebPermissionCheck webPermissionCheck)
        {
            _logger = logger;
            _webPermissionCheck = webPermissionCheck;
        }

        // Check whether a given MinimumAgeRequirement is satisfied or not for a particular context
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, WebRequirement requirement)
        {
            if (_webPermissionCheck.IsGranted(requirement.Permissions, context.User))
            {
                context.Succeed(requirement);
            }
            else
            {
                _logger.LogInformation("No Permissions");
            }

            return Task.CompletedTask;
        }
    }
}

WebAuthorizeAttribute.cs 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;

namespace WebSystem.Authorization
{

    public static class WebAutjorizeExtend
    {
        public static string[] GetPermissions(string currencyValue)
        {
            string pattern = @"[(?<content>.*?)]";


            var text = Regex.Match(currencyValue, pattern).Groups["content"].Value;

            return text.Split(",", StringSplitOptions.RemoveEmptyEntries).ToArray();

        }
    }

    public class WebAuthorizeAttribute : AuthorizeAttribute
    {
       
        const string POLICY_PREFIX = "NeedPermissions:[0]";

        public WebAuthorizeAttribute(params string[] permissions) => Permissions = permissions;

        // Get or set the Age property by manipulating the underlying Policy property
        public string[] Permissions
        {
            get
            {
                var permissions = WebAutjorizeExtend.GetPermissions(Policy);
                return permissions;

            }
            set
            {
                Policy = POLICY_PREFIX.Replace("[0]", $"[{string.Join(',', value)}]");
            }
        }
    }
}

WebPolicyProvider.cs 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;

namespace WebSystem.Authorization
{
    public class WebPolicyProvider : IAuthorizationPolicyProvider
    {
        const string POLICY_PREFIX = "NeedPermissions:";
        public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }

        public WebPolicyProvider(IOptions<AuthorizationOptions> options)
        {

            FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
        }

        public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => FallbackPolicyProvider.GetDefaultPolicyAsync();

        public Task<AuthorizationPolicy> GetFallbackPolicyAsync() => FallbackPolicyProvider.GetFallbackPolicyAsync();


        public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
        {
            if (policyName.StartsWith(POLICY_PREFIX, StringComparison.OrdinalIgnoreCase))
            {
                var permissionsArray = WebAutjorizeExtend.GetPermissions(policyName);
                if (permissionsArray.Length > 0)
                {
                    var policy = new AuthorizationPolicyBuilder();
                    policy.AddRequirements(new WebRequirement(permissionsArray));
                    return Task.FromResult(policy.Build());
                }
            }
            return FallbackPolicyProvider.GetPolicyAsync(policyName);
        }
    }
}

WebRequirement.cs 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;

namespace WebSystem.Authorization
{
    public class WebRequirement: IAuthorizationRequirement
    {
       public string[] Permissions { get; private set; }

        public WebRequirement(params string[] permissions) { Permissions = permissions; }
    }
}

使用方式:

1. 在需要的项目中添加模块依赖

 2.  实现IWebPermissionCheck 中的方法替换默认的 NullWebPermissionChecker 实现,NullWebPermissionChecker 默认所有操作都是可以的,这里自己实现是指根据权限名和数据库中保存的对比,判断是否具有相应权限

在 ConfigureServices 中进行替换默认的NullWebPermissionChecker 

  context.Services.Replace(
                ServiceDescriptor.Transient<IWebPermissionCheck, MyWebPermissionCheck>()
            );

附我自己的MyWebPermissionCheck实现方式:

using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Users;
using WebSystem.Authorization;
using WebSystem.Localization;
using WebSystem.Shared.Enums;

namespace WebSystem
{
    public class MyWebPermissionCheck : IWebPermissionCheck, ITransientDependency
    {

        public ILogger<MyWebPermissionCheck> Logger { get; set; }
        protected IPermissionDefinitionManager PermissionDefinitionManager { get; }
        private readonly IStringLocalizer<WebSystemLoaclizationResource> _localizer;
        private readonly ICurrentUser _currentUser;
        private readonly IFreeSql _orm;
        public MyWebPermissionCheck(IPermissionDefinitionManager permissionDefinitionManager, IStringLocalizer<WebSystemLoaclizationResource> stringLocalizer, ICurrentUser currentUser, IFreeSql orm)
        {
            Logger = NullLogger<MyWebPermissionCheck>.Instance;
            PermissionDefinitionManager = permissionDefinitionManager;
            _localizer = stringLocalizer;
            _currentUser = currentUser;
            _orm = orm;
        }
        public bool IsGranted(string[] needPermissions, ClaimsPrincipal user)
        {

            var claims = _currentUser.GetAllClaims();
            var userIdClaim = claims?.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier);
            long? userId = null;
            string role = string.Empty;
            if (!string.IsNullOrEmpty(userIdClaim?.Value))
            {
                userId = long.Parse(userIdClaim.Value);
            }
            else
            {
                return false;
            }

            var userRoleIdClaim = claims?.FirstOrDefault(c => c.Type == ClaimTypes.Role);
            if (!string.IsNullOrEmpty(userRoleIdClaim?.Value))
            {
                role = userRoleIdClaim.Value;
            }
            if (role == RoleEnum.Admin.ToString())
            {
                return true;
            }

            var permissions = PermissionDefinitionManager.GetPermissions();
            if (role == RoleEnum.Agent.ToString())
            {
                var agentPermissions = permissions.Where(m => (m.MultiTenancySide == Volo.Abp.MultiTenancy.MultiTenancySides.Both || m.MultiTenancySide == Volo.Abp.MultiTenancy.MultiTenancySides.Tenant) && m.IsEnabled == true);
                if (agentPermissions.Any(m => needPermissions.Contains(m.Name)))
                {
                    return true;
                }
            }
            var isAny = _orm.Select<Models.Permission>().Where(m => m.Uid == userId && needPermissions.Contains(m.Name)).Any();
            if (isAny)
            {
                return true;
            }
            return false;
        }
    }
}

3.具体使用多个权限之间使用英文逗号隔开

原文地址:https://www.cnblogs.com/lkd3063601/p/15386903.html