using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class AuthorizeAttributeDemo
{
/*
* 模块的配置
增加权限拦截器,只要类型和方法有AuthorizeAttribute都增加AuthorizationInterceptor
*/
public static void RegisterIfNeeded(IOnServiceRegisteredContext context)
{
if (ShouIdIntercept(context.ImplementationType))
{
context.Interceptors.TryAdd<AuthorizationInterceptor>();
}
}
private static bool ShouldIntercept(Type type)
{
return type.IdDefined(type(AuthorizeAttribute, true)) || AnyMethodHasAuthorizeAttribute(type);
}
/*
2 PermisstionOptions权限的两个集合,权限的定义IPermissionDefinitionProvider,以及权限的提供者IPermissionValueProvider
注册PermissionRequireHandler到DI系统里面
*/
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Service.OnRegistered(AuthorizeInterceptionRegistrar.RegisterIfNeeded);
AutoAddDefinitionProviders(context.Services);
}
public override void ConfigureService(ServiceConfigurationContext context)
{
context.Service.AddAuthorization();
context.Service.AddSingleton<IAuthorizationHandler, PermissionRequirementHandler>();
Configure<PermissionOPtions>(options =>
{
options.valueProviders.Add<UserPermissionValueProvider>();
options.ValueProviders.Add<RolePermissionValueProvider>();
options.ValueProviders.Add<ClientPermissionValueValueProvider>();
});
}
/*
PermissionDefinition的定义有,名称,父定义Parent,租户端(Tenant,Host,Both),允许providers(指的valueProvider)显示名字
子权限Children列表List<PermissionDefinition>,客户端属性定义Dictionary<string,object>Properties,WithProperty,WithProviders
两个方法设置
2、PermissionGroupDefinition组定义,基本同PermissionDefinition,重点方法GetPermissionsWithChildren,是递归获取所有的PermissionDefinition
3PermissionDefinitionContext,是组定义字典的Dictionary<string,PermissionGroupDefinition>Groups,及一些方法AddGroup
GetGroupOrNull方法
4IPermissionDefinitionManager,有组的定义,也有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要鉴权的权限定义以及ClamsPrincipal(用户的信息)
PermissionValueCheckContext的构建见PermissionChecker类,它是调用PermissionValueProvider来获取是否存在权限
var context = new PermissionValueCheckContext(permission,claimsPrincipal)
IPermissionValueProvider的抽象方法PermissionValueProvider,注入IPermissionStore
*/
public abstract class PermissionValueProvider : IPermissionValueProvider, ISingleDependency //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,用户AbpClaimType.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.IsGrantAsync(context.Permission.Name, nameof, 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.GetMuliTenancySide();
if (!permission.MultiTenancySide.HasFlag(multiTenancySide))
{
return false;
}
var isGranted = false;
var context = new PermissionValueCheckContext(permission,claimsPrincipal);
foreach (var provider in ValueProviders)
{
if (context.Permission.Provider.Any()&&!context.Permission.Providers.Contains(provider.Name))
{
continue;
}
}
var result = await EncodingProvider.CheckAsync(context);
if (result = PermissionGrantResult.Granted)
{
isGranted = true;
}
else if (result == PermissionGrantResult.Prohibited)
{
return false;
}
return isGranted;
}
protected async Task CheckAsync(IAuthorizeData authorizationAttribute)
{
if (authorizationAttribute.Policy == null)
{
if (!_currentUser.IsAuthenticated&&!_currentClient.IsAuthenticated)
{
throw new AbpAuthorizationException("Authorzation failed!User has not loggin in");
}
}
else
{
await _authorizationService.CheckAsync(authorizationAttribute.Policy);
}
}
}
/*
IMehtodInvocationAuthorizationService,用于拦截器
Asp.net Core的认证和授权,Abp进行集成
基于策略的授权是授权的核心,基于角色的授权和基于Scheme的授权只是一种语法上的边界,最终都会生成授权策略
使用基于策略的授权时,首先要定义授权策略,而授权策略本质上就是对Claims的一系列的断言
每一个Requirement都代表一个授权条件,比如DenyAnonymousAuthorizationRequirement表示禁止匿名用户访问的授权策略
ClaimsAuthorizationReuqirement用于表示判断Cliams中是否包含预期的Claims的授权策略
因此,我们先定义一个代表操作的Requirement
*/
public class PermissionRequirement : IAuthorizationRequirement
{
public string PermissionName { get; }
public PermissionRequirement([NotNull]string permissionName)
{
checked.NotNull(permissionName,nameof(permissionName));
PermissionName = PermissionName;
}
}
/*
每一个Requirement都需要有一个对应的Handler,来完成授权逻辑,可以直接让Requirement实现IAuthorizationHandler接口
也可以单独定义授权Handler
我们在实现IAuthorzationHandler接口时,通常是继承自AuthorizationHandler<TRequirement>来实现,它有如下定义
依赖于_permissionChecker进行验证
*/
public class PermissionRequirementHandler : AuthorzationHandler<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对象,要判断的用户是否具有针对该资源的某项操作
AuthorizationPlicyBuilder它提供了一系列创建AuthorizationPolicy的快捷方法
IAuthorizationPolicyProvider是根据名臣获取到策略对象,默认时限为DefaultAuthorizationPolicyProvider
从AuthorizationOptions _options里面获取_options.GetPolicy(policyName)
ABP自定义AbpAuthorizationPolicyProvider,派生DefautAuthorizationPolicyProvider,在GetPolicyAsync方法里从
IPermissionDefinicationManager得到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)
{
AuthorizationPolicyBuilder(Array.Empty<string>());
policyBuilder.Requirements.Add(new PermissionRequirement(policyName));
return policyBuilder.Build();
}
return null;
}
/*
权限主要通过调用IAuthorizationService来完成的,而授权策略的本质是提供Requrement,我们完全可以使用他们两个来完成各种灵活的授权方式
而不用局限于策略,在默认的AuthorizationHandlerProvider中,会从DI系统获取我们注册的所有Handler
最终调用其HandleAsync方法
*/
public class DefaultAuthorizationService : IAuthorizationService
{
private readonly AuthorizationOptions _options1;
private readonly IAuthorizationHandlerContextFactory _contextFactory;
private readonly IAuthorizationHanlerProvider _handlers;
private readonly IAuthorzationEvaluator _evaluator;
private readonly IAuthorizationPl authorizationPl;
}
}