最终返回的是一个PolicyAuthorizationResult对象,并在授权失败时,根据认证结果来返回Forbid(未授权)或Challenge(未登录)。
public class PolicyAuthorizationResult { private PolicyAuthorizationResult() { } public bool Challenged { get; private set; } public bool Forbidden { get; private set; } public bool Succeeded { get; private set; } } IAuthorizationService然后就到了授权的核心对象AuthorizationService,也可以称为授权的外交官,我们也可以直接在应用代码中调用该对象来实现授权,它有如下定义:
public interface IAuthorizationService { Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName); Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements); }在AuthorizeAsync中还涉及到一个resource对象,用来实现面向资源的授权,放在下一章中再来介绍,而在本章与《前一章》的示例中,该值均为null。
ASP.NET Core 中还为IAuthorizationService提供了几个扩展方法:
public static class AuthorizationServiceExtensions { public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, string policyName) {} public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, AuthorizationPolicy policy) {} public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, object resource, IAuthorizationRequirement requirement) {} public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, object resource, AuthorizationPolicy policy) {} }其默认实现为DefaultAuthorizationService:
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); } }通过上面代码可以看出,在《上一章》中介绍的授权策略,在这里获取到它的Requirements,后续便不再需要了。而在AuthorizationService中是通过调用四大核心对象来完成授权,我们一一来看。
IAuthorizationPolicyProvider由于在[Authorize]中,我们指定的是策略的名称,因此需要使用IAuthorizationPolicyProvider来根据名称获取到策略对象,默认实现为DefaultAuthorizationPolicyProvider:
public class DefaultAuthorizationPolicyProvider : IAuthorizationPolicyProvider { private readonly AuthorizationOptions _options; public Task<AuthorizationPolicy> GetDefaultPolicyAsync() { return Task.FromResult(_options.DefaultPolicy); } public virtual Task<AuthorizationPolicy> GetPolicyAsync(string policyName) { return Task.FromResult(_options.GetPolicy(policyName)); } }在上一章中介绍过,我们定义的策略都保存在《AuthorizationOptions》的字典中,因此在这里只是简单的将AuthorizationOptions中的同名方法异步化。
IAuthorizationHandlerContextFactory授权上下文是我们接触较多的对象,当我们自定义授权Handler时就会用到它,它是使用简单工厂模式来创建的:
public class DefaultAuthorizationHandlerContextFactory : IAuthorizationHandlerContextFactory { public virtual AuthorizationHandlerContext CreateContext(IEnumerable<IAuthorizationRequirement> requirements, ClaimsPrincipal user, object resource) { return new AuthorizationHandlerContext(requirements, user, resource); } }授权上下文中主要包含用户的Claims和授权策略的Requirements:
public class AuthorizationHandlerContext { private HashSet<IAuthorizationRequirement> _pendingRequirements; private bool _failCalled; private bool _succeedCalled; public AuthorizationHandlerContext(IEnumerable<IAuthorizationRequirement> requirements, ClaimsPrincipal user, object resource) { Requirements = requirements; User = user; Resource = resource; _pendingRequirements = new HashSet<IAuthorizationRequirement>(requirements); } public virtual bool HasFailed { get { return _failCalled; } } public virtual bool HasSucceeded => !_failCalled && _succeedCalled && !_pendingRequirements.Any(); public virtual void Fail() { _failCalled = true; } public virtual void Succeed(IAuthorizationRequirement requirement) { _succeedCalled = true; _pendingRequirements.Remove(requirement); } }如上,_pendingRequirements中保存着所有待验证的Requirements,验证成功的Requirement则从中移除。
IAuthorizationHandlerProvider兜兜转转,终于进入到了授权的最终验证逻辑中了,首先,使用IAuthorizationHandlerProvider来获取到所有的授权Handler。