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.具体使用多个权限之间使用英文逗号隔开

 

posted on   落叶子  阅读(317)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2017-10-09 ionic 入口禁止加载其他页面

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示