权限模块

一、模块的配置

1、增加权限拦截器,只要类型和方法有AuthorizeAttribute都增加AuthorizationInterceptor

     public static void RegisterIfNeeded(IOnServiceRegistredContext context)
        {
            if (ShouldIntercept(context.ImplementationType))
            {
                context.Interceptors.TryAdd<AuthorizationInterceptor>();
            }
        }

        private static bool ShouldIntercept(Type type)
        {
            return type.IsDefined(typeof(AuthorizeAttribute), true) ||
                   AnyMethodHasAuthorizeAttribute(type);
        }

2、PermissionOptions权限的两个集合,权限的定义IPermissionDefinitionProvider,以及权限的提供者IPermissionValueProvider

注册PermissionRequirementHandler到DI系统里面

 public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.OnRegistred(AuthorizationInterceptorRegistrar.RegisterIfNeeded);
            AutoAddDefinitionProviders(context.Services);
        }

        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddAuthorization();

            context.Services.AddSingleton<IAuthorizationHandler, PermissionRequirementHandler>();

            Configure<PermissionOptions>(options =>
            {
                options.ValueProviders.Add<UserPermissionValueProvider>();
                options.ValueProviders.Add<RolePermissionValueProvider>();
                options.ValueProviders.Add<ClientPermissionValueProvider>();
            });
        }

1)PermissionDefinition的定义有,名称,父定义Parent ,租户端(Tenant,Host,Both),允许providers(指的valueProvider) ,显示名字,子权限Children列表List<PermissionDefinition>,客户化属性定义Dictionary<string, object> Properties,WithProperty,WithProviders两个方法设置   

2、PermissionGroupDefinition组定义,基本同PermissionDefinition,重点方法GetPermissionsWithChildren,是递归获取所有的PermissionDefinition。

3、PermissionDefinitionContext,是组定义字典的Dictionary<string, PermissionGroupDefinition> Groups,及一些方法AddGroup,GetGroupOrNull方法

4、IPermissionDefinitionManager,有组的定义,也有PermissionDefinition的方法,构造函数遍历Options.DefinitionProviders,遍历实现中Define方法,填充PermissionDefinitionContext,返回PermissionGroupDefinition的字典

 protected virtual Dictionary<string, PermissionGroupDefinition> CreatePermissionGroupDefinitions()
        {
            var context = new PermissionDefinitionContext();

            using (var scope = _serviceProvider.CreateScope())
            {
                var providers = Options
                    .DefinitionProviders
                    .Select(p => scope.ServiceProvider.GetRequiredService(p) as IPermissionDefinitionProvider)
                    .ToList();

                foreach (var provider in providers)
                {
                    provider.Define(context);
                }
            }

            return context.Groups;
        }

  2 权限的提供者IPermissionValueProvider(三个分别是用户、角色和客户端),其主要方法 Task<PermissionGrantResult> CheckAsync(PermissionValueCheckContext context);返回是结果是Undefined,Granted,Prohibited的其中的一个

 其中:PermissionValueCheckContext的上下文要引入PermissionDefinition要鉴权的权限定义以及ClaimsPrincipal(用户的信息)。PermissionValueCheckContext的构建见PermissionChecker类;它是调用IPermissionValueProvider来获取是否存在权限;var context = new PermissionValueCheckContext(permission, claimsPrincipal);

 

IPermissionValueProvider的抽象方法PermissionValueProvider,注入IPermissionStore

 public abstract class PermissionValueProvider : IPermissionValueProvider, ISingletonDependency  //TODO: to transient?
    {
        public abstract string Name { get; }

        protected IPermissionStore PermissionStore { get; }

        protected PermissionValueProvider(IPermissionStore permissionStore)
        {
            PermissionStore = permissionStore;
        }

        public abstract Task<PermissionGrantResult> CheckAsync(PermissionValueCheckContext context);
    }

 其一实现方法:用户UserPermissionValueProvider,用户AbpClaimTypes.UserId,角色AbpClaimTypes.Role,客户端AbpClaimTypes.ClientId,同理。

  public override async Task<PermissionGrantResult> CheckAsync(PermissionValueCheckContext context)
        {
            var userId = context.Principal?.FindFirst(AbpClaimTypes.UserId)?.Value;

            if (userId == null)
            {
                return PermissionGrantResult.Undefined;
            }

            return await PermissionStore.IsGrantedAsync(context.Permission.Name, Name, userId)
                ? PermissionGrantResult.Granted
                : PermissionGrantResult.Undefined;
        }

二、IPermissionChecker是检查既定的认证信息是否有权限,见构造函数

public PermissionChecker(
            IOptions<PermissionOptions> options,
            IServiceProvider serviceProvider,
            ICurrentPrincipalAccessor principalAccessor,
            IPermissionDefinitionManager permissionDefinitionManager, 
            ICurrentTenant currentTenant)
        {
            PrincipalAccessor = principalAccessor;
            PermissionDefinitionManager = permissionDefinitionManager;
            CurrentTenant = currentTenant;
            Options = options.Value;

            _lazyProviders = new Lazy<List<IPermissionValueProvider>>(
                () => Options
                    .ValueProviders
                    .Select(c => serviceProvider.GetRequiredService(c) as IPermissionValueProvider)
                    .ToList(),
                true
            );
        }

  这是权限判断的方法,遍历IPermissionValueProvider在Options里面ValueProviders字典

  public virtual async Task<bool> IsGrantedAsync(ClaimsPrincipal claimsPrincipal, string name)
        {
            Check.NotNull(name, nameof(name));

            var permission = PermissionDefinitionManager.Get(name);

            var multiTenancySide = claimsPrincipal?.GetMultiTenancySide()
                                   ?? CurrentTenant.GetMultiTenancySide();

            if (!permission.MultiTenancySide.HasFlag(multiTenancySide))
            {
                return false;
            }

            var isGranted = false;
            var context = new PermissionValueCheckContext(permission, claimsPrincipal);
            foreach (var provider in ValueProviders)
            {
                if (context.Permission.Providers.Any() &&
                    !context.Permission.Providers.Contains(provider.Name))
                {
                    continue;
                }

                var result = await provider.CheckAsync(context);

                if (result == PermissionGrantResult.Granted)
                {
                    isGranted = true;
                }
                else if (result == PermissionGrantResult.Prohibited)
                {
                    return false;
                }
            }

            return isGranted;
        }
    

 4、IMethodInvocationAuthorizationService,用于拦截器

      protected async Task CheckAsync(IAuthorizeData authorizationAttribute)
        {
            if (authorizationAttribute.Policy == null)
            {
                //TODO: Can we find a better, unified, way of checking if current request has been authenticated
                if (!_currentUser.IsAuthenticated && !_currentClient.IsAuthenticated)
                {
                    throw new AbpAuthorizationException("Authorization failed! User has not logged in.");
                }
            }
            else
            {
                await _authorizationService.CheckAsync(authorizationAttribute.Policy);
            }

            //TODO: What about roles and other props?
        }

 Asp.net Core的认证和授权,ABP进行集成

基于策略的授权是授权的核心,基于角色的授权和基于Scheme的授权,只是一种语法上的便捷,最终都会生成授权策略,使用基于策略的授权时,首先要定义授权策略,而授权策略本质上就是对Claims的一系列断言。

 每一个Requirement都代表一个授权条件;比如DenyAnonymousAuthorizationRequirement 表示禁止匿名用户访问的授权策略;ClaimsAuthorizationRequirement 用于表示判断Cliams中是否包含预期的Claims的授权策略。

因此,我们先定义一个代表操作的Requirement:

   public class PermissionRequirement : IAuthorizationRequirement
    {
        public string PermissionName { get; }

        public PermissionRequirement([NotNull]string permissionName)
        {
            Check.NotNull(permissionName, nameof(permissionName));

            PermissionName = permissionName;
        }
    }

 每一个 Requirement 都需要有一个对应的 Handler,来完成授权逻辑,可以直接让 Requirement 实现IAuthorizationHandler接口,也可以单独定义授权Handler

我们在实现IAuthorizationHandler接口时,通常是继承自AuthorizationHandler<TRequirement>来实现,它有如下定义:

依赖于_permissionChecker进行验证

public class PermissionRequirementHandler : AuthorizationHandler<PermissionRequirement>
    {
        private readonly IPermissionChecker _permissionChecker;

        public PermissionRequirementHandler(IPermissionChecker permissionChecker)
        {
            _permissionChecker = permissionChecker;
        }

        protected override async Task HandleRequirementAsync(
            AuthorizationHandlerContext context,
            PermissionRequirement requirement)
        {
            if (await _permissionChecker.IsGrantedAsync(context.User, requirement.PermissionName))
            {
                context.Succeed(requirement);
            }
        }
    }

授权策略具体表现为一个AuthorizationPolicy对象,要判断的是用户是否具有针对该资源的某项操作,AuthorizationPolicyBuilder,它提供了一系列创建AuthorizationPolicy的快捷方法。

IAuthorizationPolicyProvider是根据名称获取到策略对象,默认实现为DefaultAuthorizationPolicyProvider,从AuthorizationOptions _options里面获取_options.GetPolicy(policyName)

ABP自定义AbpAuthorizationPolicyProvider,派生DefaultAuthorizationPolicyProvider,在GetPolicyAsync方法里从IPermissionDefinitionManager得到permissiondefinition的定义,再利用AuthorizationPolicyBuilder创建AuthorizationPolicy对象

 public override async Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
        {
            var policy = await base.GetPolicyAsync(policyName);
            if (policy != null)
            {
                return policy;
            }

            var permission = _permissionDefinitionManager.GetOrNull(policyName);
            if (permission != null) { //TODO: Optimize & Cache! var policyBuilder = new AuthorizationPolicyBuilder(Array.Empty<string>()); policyBuilder.Requirements.Add(new PermissionRequirement(policyName)); return policyBuilder.Build(); } return null; }

 

 

权限是主要是通过调用IAuthorizationService来完成的,而授权策略的本质是提供 Requirement ,我们完全可以使用它们两个来完成各种灵活的授权方式,而不用局限于策略;在默认的AuthorizationHandlerProvider中,会从DI系统中获取到我们注册的所有Handler,最终调用其HandleAsync方法。;

public class DefaultAuthorizationService : IAuthorizationService
{
    private readonly AuthorizationOptions _options;
    private readonly IAuthorizationHandlerContextFactory _contextFactory;
    private readonly IAuthorizationHandlerProvider _handlers;
    private readonly IAuthorizationEvaluator _evaluator;
    private readonly IAuthorizationPolicyProvider _policyProvider;

    public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName)
    {        
        var policy = await _policyProvider.GetPolicyAsync(policyName);
        return await this.AuthorizeAsync(user, resource, policy);
    }

    public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)
    {
        var authContext = _contextFactory.CreateContext(requirements, user, resource);
        var handlers = await _handlers.GetHandlersAsync(authContext);
        foreach (var handler in handlers)
        {
            await handler.HandleAsync(authContext);
            if (!_options.InvokeHandlersAfterFailure && authContext.HasFailed)
            {
                break;
            }
        }
        return _evaluator.Evaluate(authContext);
    }
}

 

public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandler where TRequirement : IAuthorizationRequirement
{
    public virtual async Task HandleAsync(AuthorizationHandlerContext context)
    {
        foreach (var req in context.Requirements.OfType<TRequirement>())
        {
            await HandleRequirementAsync(context, req);
        }
    }

    protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement);

 

 public class PermissionRequirementHandler : AuthorizationHandler<PermissionRequirement>
    {
        private readonly IPermissionChecker _permissionChecker;

        public PermissionRequirementHandler(IPermissionChecker permissionChecker)
        {
            _permissionChecker = permissionChecker;
        }

        protected override async Task HandleRequirementAsync(
            AuthorizationHandlerContext context,
            PermissionRequirement requirement)
        {
            if (await _permissionChecker.IsGrantedAsync(context.User, requirement.PermissionName))
            {
                context.Succeed(requirement);
            }
        }
    }

转载于:https://www.cnblogs.com/cloudsu/p/11179967.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值