本系列将分析 ASP.NET Core 运行原理
在认证阶段通过用户令牌获取到用户的 Claims,而授权就是对这些 Claims 的验证。
- services.AddAuthorization(opt = >opt.AddPolicy("isAdmin", builder = >builder.RequireUserName("admin")));
通过上面的代码,可以添加一个 isAdmin 的授权。
对于第一个参数 opt:
- public class AuthorizationOptions {
- private IDictionary < string,
- AuthorizationPolicy > PolicyMap {
- get;
- } = new Dictionary < string,
- AuthorizationPolicy > ();
- public void AddPolicy(string name, AuthorizationPolicy policy) {
- PolicyMap[name] = policy;
- }
- public void AddPolicy(string name, Action < AuthorizationPolicyBuilder > configurePolicy) {
- var policyBuilder = new AuthorizationPolicyBuilder();
- configurePolicy(policyBuilder);
- AddPolicy(name, policyBuilder.Build());
- }
- public AuthorizationPolicy GetPolicy(string name) {
- return PolicyMap.ContainsKey(name) ? PolicyMap[name] : null;
- }
- }
实际上,
相当于 AuthorizationPolicy 的集合
- AuthorizationOptions
而 AuthorizationPolicy 则是一个具体的授权策略对象
- public class AuthorizationPolicy
- {
- public IReadOnlyList<IAuthorizationRequirement> Requirements { get; }
- public IReadOnlyList<string> AuthenticationSchemes { get; }
- }
而
通过 Build 方法可以构建一个 AuthorizationPolicy,其内部有很多常用的添加
- AuthorizationPolicyBuilder
的方法:
- IAuthorizationRequirement
- public AuthorizationPolicy Build()
- {
- return new AuthorizationPolicy(this.Requirements, this.AuthenticationSchemes);
- }
- public AuthorizationPolicyBuilder RequireUserName(string userName)
- {
- this.Requirements.Add(new NameAuthorizationRequirement(userName));
- }
- ... Require() ...
是授权策略 AuthorizationPolicy 的一个授权条件, 策略下的所有授权条件满足,则授权成功。
- IAuthorizationRequirement
- public interface IAuthorizationRequirement
- {
- }
- public class NameAuthorizationRequirement : IAuthorizationRequirement
- {
- public string RequiredName { get; }
- }
是授权条件
- IAuthorizationHandler
的具体处理器,授权条件下的任意 1 个处理器授权成功,则授权成功。(默认情况下:AuthorizationOptions 的 InvokeHandlersAfterFailure = true)
- IAuthorizationRequirement
- public interface IAuthorizationHandler
- {
- Task HandleAsync(AuthorizationHandlerContext context);
- }
- public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandler where TRequirement : IAuthorizationRequirement
- {
- public virtual async Task HandleAsync(AuthorizationHandlerContext context)
- {
- foreach (TRequirement requirement in context.Requirements)
- await HandleRequirementAsync(context, requirement);
- }
- protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement);
- }
- public class NameAuthorizationRequirement : AuthorizationHandler<NameAuthorizationRequirement>
- {
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, NameAuthorizationRequirement requirement)
- {
- if (context.User?.Identities.Any(identity => identity.Name == requirement.RequiredName))
- context.Succeed((IAuthorizationRequirement) requirement);
- return Task.CompletedTask;
- }
- }
授权的最终实现代码在 IAuthorizationHandler
解释了授权策略的原理,再谈谈授权策略的触发。通常我们在 MVC 中使用授权功能,而触发授权也是在注册 MVC 代码中,一并注册了。
- public static IMvcBuilder AddMvc(this IServiceCollection services)
- {
- IMvcCoreBuilder builder = services.AddMvcCore();
- builder.AddAuthorization();
- }
- internal static void AddAuthorizationServices(IServiceCollection services)
- {
- services.AddAuthenticationCore();
- services.AddAuthorization();
- services.AddAuthorizationPolicyEvaluator();
- services.TryAddEnumerable(ServiceDescriptor.Transient<IApplicationModelProvider, AuthorizationApplicationModelProvider>());
- }
在 MVC 中,ApplicationModel 用来描述 MVC 中的模型,而 IApplicationModelProvider 则是初始化 MVC 的模型:
- public class ApplicationModel
- {
- public IList<ControllerModel> Controllers { get; }
- public IList<IFilterMetadata> Filters { get; }
- }
- public interface IApplicationModelProvider
- {
- int Order { get; }
- void OnProvidersExecuting(ApplicationModelProviderContext context);
- void OnProvidersExecuted(ApplicationModelProviderContext context);
- }
其中 AuthorizationApplicationModelProvider 会初始化 ApplicationModel 的授权部分,注册到 Filters 属性上(AuthorizeFilter 和 AllowAnonymousFilter)。
- public interface IAsyncAuthorizationFilter : IFilterMetadata
- {
- Task OnAuthorizationAsync(AuthorizationFilterContext context);
- }
- public class AuthorizeFilter : IAsyncAuthorizationFilter
- {
- public virtual async Task OnAuthorizationAsync(AuthorizationFilterContext context)
- {
- var policyEvaluator = GetRequiredService<IPolicyEvaluator>();
- var authenticationResult = await policyEvaluator.AuthenticateAsync(effectivePolicy, context.HttpContext);
- var authorizationResult = await policyEvaluator.AuthorizeAsync(effectivePolicy, authenticationResult, context.HttpContext, context);
- if (authorizationResult.Challenged)
- {
- context.Result = (IActionResult) new ChallengeResult((IList<string>) effectivePolicy.AuthenticationSchemes.ToArray<string>());
- }
- else if (authorizationResult.Forbidden)
- {
- context.Result = (IActionResult) new ForbidResult((IList<string>) effectivePolicy.AuthenticationSchemes.ToArray<string>());
- }
- }
- }
AuthorizeFilter 的 OnAuthorizationAsync 方法会在 Action 执行前触发,内部调用 IPolicyEvaluator 执行
- public interface IPolicyEvaluator
- {
- Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context);
- Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource);
- }
- public class PolicyEvaluator : IPolicyEvaluator
- {
- private readonly IAuthorizationService _authorization;
- public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
- {
- }
- public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource)
- {
- var result = await _authorization.AuthorizeAsync(context.User, resource, policy);
- if (result.Succeeded) return PolicyAuthorizationResult.Success();
- return (authenticationResult.Succeeded) ? PolicyAuthorizationResult.Forbid() : PolicyAuthorizationResult.Challenge();
- }
- }
在 AuthenticateAsync 方法中,将合并 policy 的所有 scheme 认证结果。
在 AuthorizeAsync 方法中,将调用
来实现授权。
- IAuthorizationService
- public interface IAuthorizationService
- {
- Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements);
- Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName);
- }
- public class DefaultAuthorizationService : IAuthorizationService
- {
- 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);
- }
- }
在 IAuthorizationService 类中,将调用 policy 的所有 Requirement 的 Handle 处理
授权核心:
、AuthorizationPolicy、
- AuthorizationOptions
- AuthorizationPolicyBuilder
AuthorizationOptions 用于保存 AuthorizationPolicy
AuthorizationPolicyBuilder 用于创建 AuthorizationPolicy
AuthorizationPolicy 包含 IAuthorizationRequirement 和 AuthenticationSchemes
IAuthorizationRequirement 包含授权逻辑 IAuthorizationHandler
执行授权:AuthorizeFilter、IPolicyEvaluator、
- IAuthorizationService
AuthorizeFilter 的 OnAuthorizationAsync 方法会在 Action 执行前触发,内部调用 IPolicyEvaluator 执行
IPolicyEvaluator 先根据 Schemes 获取 Claims,然后调用 IAuthorizationService 的授权方法
IAuthorizationService 调用 Requirement 对应的 Handle 授权逻辑
个人觉得源码的一个待优化的地方:在
的 GetHandlersAsync 方法按需返回
- DefaultAuthorizationHandlerProvider
更合适。
- IAuthorizationHandler
本文链接: http://www.cnblogs.com/neverc/p/8204339.html
来源: https://www.cnblogs.com/neverc/p/8204339.html