上一篇分析了IPolicyEvaluator.AuthenticateAsync的过程,今天继续:
IPolicyEvaluator.AuthorizeAsync,判断权限的过程
补记录,AuthorizationMiddleware.Invoke方法中,在完成IPolicyEvaluator.AuthenticateAsync后,继续判断是否匿名,如果是的话,直接交给下一个中间件,如果不是,继续执行IPolicyEvaluator.AuthorizeAsync,其代码如下。
// Allow Anonymous still wants to run authorization to populate the User but skips any failure/challenge handling
if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null)
{
await _next(context);
return;
}
policyEvaluator.AuthorizeAsync(policy, authenticateResult!, context, resource);
A、IAuthorizationService(实现类DefaultAuthorizationService).AuthorizeAsync
方法入口参数:
public virtual async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object? resource, IEnumerable<IAuthorizationRequirement> requirements)
B、创建AuthorizationHandlerContext
通过 IAuthorizationHandlerContextFactory.CreateContext创建
C、获得本次权限验证类相关的 IAuthorizationHandler实现类集合
通过 IAuthorizationHandlerProvider(默认实现类 DefaultAuthorizationHandlerProvider).GetHandlersAsync 获得
D、遍历计算权限验证各种规则,如果配置中InvokeHandlersAfterFailure为False,则有一个失败,立刻跳出遍历,否则每一条规则都需要进行验证
遍历 IAuthorizationHandler集合,对每一个实现了AuthorizationHandler子类,执行其HandleAsync,实际执行HandleRequirementAsync方法
E、以RolesAuthorizationRequirement为例,代码如下,判断需要的Role在用户自身Role中是否存在,如果存在,就是Succeed。
/// <summary>
/// Makes a decision if authorization is allowed based on a specific requirement.
/// </summary>
/// <param name="context">The authorization context.</param>
/// <param name="requirement">The requirement to evaluate.</param>
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesAuthorizationRequirement requirement)
{
if (context.User != null)
{
bool found = false;
if (requirement.AllowedRoles == null || !requirement.AllowedRoles.Any())
{
// Review: What do we want to do here? No roles requested is auto success?
}
else
{
found = requirement.AllowedRoles.Any(r => context.User.IsInRole(r));
}
if (found)
{
context.Succeed(requirement);
}
}
return Task.CompletedTask;
}
F、判断结束,根据规则结果来计算成功失败
执行 IAuthorizationEvaluator(默认实现类DefaultAuthorizationEvaluator)下的Evaluate方法。
其基于 AuthorizationHandlerContext 中的 HasSucceeded 或 HasFailed 来判断
如果成功,则返回 PolicyAuthorizationResult.Success()
如果失败,则需要看上一篇身份验证那里的结果。
身份验证失败,则返回 PolicyAuthorizationResult.Challenge , 转入身份验证页面。
身份验证成功,则返回 PolicyAuthorizationResult.Forbid , 转入权限不足页面。