回顾:基于.NetCore3.1系列 —— 认证受权方案之受权揭秘 (上篇)html
在上一篇中,主要讲解了受权在配置方面的源码,从添加受权配置开始,咱们引入了须要的受权配置选项,而不一样的受权要求构建不一样的策略方式,从而实现一种本身满意的受权需求配置要求。git
在这一节中,继续上一篇的内容往下深刻了解受权内部机制的奥秘以及是如何实现执行受权流程的。github
在上一篇中,咱们经过定义受权策略,查看源码发现,在对受权配置AuthorizationOptions
以后,受权系统经过DI的方式注册了几个核心的默认实现。c#
以前咱们进行对步骤一的受权有了大概了解,因此下面咱们将对步骤二进行的注册对象进行说明。app
受权服务接口,用来肯定受权是否成功的主要服务,接口的定义为asp.net
public interface IAuthorizationService { Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements); Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName); }
两个接口的参数不一样之处在于IAuthorizationRequirement
和policyName
,分别是指定资源的一组特定要求和指定的受权名称。async
同时asp.net core还为IAuthorizationService
接口拓展了几个方法:ide
public static class AuthorizationServiceExtensions { public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, object resource, IAuthorizationRequirement requirement) { if (service == null) { throw new ArgumentNullException(nameof(service)); } if (requirement == null) { throw new ArgumentNullException(nameof(requirement)); } return service.AuthorizeAsync(user, resource, new IAuthorizationRequirement[] { requirement }); } public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, object resource, AuthorizationPolicy policy) { if (service == null) { throw new ArgumentNullException(nameof(service)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } return service.AuthorizeAsync(user, resource, policy.Requirements); } public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, AuthorizationPolicy policy) { if (service == null) { throw new ArgumentNullException(nameof(service)); } if (policy == null) { throw new ArgumentNullException(nameof(policy)); } return service.AuthorizeAsync(user, resource: null, policy: policy); } public static Task<AuthorizationResult> AuthorizeAsync(this IAuthorizationService service, ClaimsPrincipal user, string policyName) { if (service == null) { throw new ArgumentNullException(nameof(service)); } if (policyName == null) { throw new ArgumentNullException(nameof(policyName)); } return service.AuthorizeAsync(user, resource: null, policyName: policyName); } }
接口的默认实现为DefaultAuthorizationService函数
DefaultAuthorizationService
的实现主要是用来对 IAuthorizationRequirement对象的受权检验。学习
public class DefaultAuthorizationService : IAuthorizationService { private readonly AuthorizationOptions _options; private readonly IAuthorizationHandlerContextFactory _contextFactory; private readonly IAuthorizationHandlerProvider _handlers; private readonly IAuthorizationEvaluator _evaluator; private readonly IAuthorizationPolicyProvider _policyProvider; private readonly ILogger _logger; public DefaultAuthorizationService(IAuthorizationPolicyProvider policyProvider, IAuthorizationHandlerProvider handlers, ILogger<DefaultAuthorizationService> logger, IAuthorizationHandlerContextFactory contextFactory, IAuthorizationEvaluator evaluator, IOptions<AuthorizationOptions> options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } if (policyProvider == null) { throw new ArgumentNullException(nameof(policyProvider)); } if (handlers == null) { throw new ArgumentNullException(nameof(handlers)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (contextFactory == null) { throw new ArgumentNullException(nameof(contextFactory)); } if (evaluator == null) { throw new ArgumentNullException(nameof(evaluator)); } _options = options.Value; _handlers = handlers; _policyProvider = policyProvider; _logger = logger; _evaluator = evaluator; _contextFactory = contextFactory; } public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements) { if (requirements == null) { throw new ArgumentNullException(nameof(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; } } var result = _evaluator.Evaluate(authContext); if (result.Succeeded) { _logger.UserAuthorizationSucceeded(); } else { _logger.UserAuthorizationFailed(); } return result; } public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName) { if (policyName == null) { throw new ArgumentNullException(nameof(policyName)); } var policy = await _policyProvider.GetPolicyAsync(policyName); if (policy == null) { throw new InvalidOperationException($"No policy found: {policyName}."); } return await this.AuthorizeAsync(user, resource, policy); } }
经过上面的代码能够发现,在对象实例中,经过构造函数的方式分别注入了IAuthorizationPolicyProvider
、IAuthorizationHandlerProvider
、IAuthorizationEvaluator
、IAuthorizationHandlerContextFactory
这几个核心服务,以及配置选项的AuthorizationOptions对象,再经过实现的方法AuthorizeAsync
能够看出,在方法中调用GetPolicyAsync
来获取Requirements
,具体的能够看一下上一节的AuthorizationPolicy,然后在根据受权上下文来判断。
这里就用到了注入的几个核心对象来实现完成受权的。下面会分别介绍到的。
由上面的IAuthorizationServer
接口的默认实现能够发现,在进行受权检验的时候,DefaultAuthorizationService
会利用注入的IAuthorizationPolicyProvider
服务来提供注册的受权策略,因此咱们查看源码发现,接口提供 了默认的受权策略GetDefaultPolicyAsync
和指定名称的受权策略·GetPolicyAsync(string policyName)
的方法。
public interface IAuthorizationPolicyProvider { Task<AuthorizationPolicy> GetPolicyAsync(string policyName); Task<AuthorizationPolicy> GetDefaultPolicyAsync(); Task<AuthorizationPolicy> GetFallbackPolicyAsync(); }
再加上在使用[Authorize]
进行策略受权的时候,会根据提供的接口方法来获取指定的受权策略。
IAuthorizationPolicyProvider
来根据名称获取到策略对象,默认实现为DefaultAuthorizationPolicyProvider
:
DefaultAuthorizationPolicyProvider
public class DefaultAuthorizationPolicyProvider : IAuthorizationPolicyProvider { private readonly AuthorizationOptions _options; private Task<AuthorizationPolicy> _cachedDefaultPolicy; private Task<AuthorizationPolicy> _cachedFallbackPolicy; public DefaultAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options) { if (options == null) { throw new ArgumentNullException(nameof(options)); } _options = options.Value; } public Task<AuthorizationPolicy> GetDefaultPolicyAsync() { return GetCachedPolicy(ref _cachedDefaultPolicy, _options.DefaultPolicy); } public Task<AuthorizationPolicy> GetFallbackPolicyAsync() { return GetCachedPolicy(ref _cachedFallbackPolicy, _options.FallbackPolicy); } private Task<AuthorizationPolicy> GetCachedPolicy(ref Task<AuthorizationPolicy> cachedPolicy, AuthorizationPolicy currentPolicy) { var local = cachedPolicy; if (local == null || local.Result != currentPolicy) { cachedPolicy = local = Task.FromResult(currentPolicy); } return local; } public virtual Task<AuthorizationPolicy> GetPolicyAsync(string policyName) { return Task.FromResult(_options.GetPolicy(policyName)); } }
由上面的代码能够看出,在实现DefaultAuthorizationPolicyProvider
对象进行构造函数的方式注入了IOptions<AuthorizationOptions> options
服务来提供配置选项AuthorizationOptions
(不懂的能够查看上一篇的AuthorizationOptions),再经过实现的方法能够看出是如何获取到注册的受权策略的了。附加一个图片
在上一章中介绍过,咱们定义的策略都保存在AuthorizationOptions的中PolicyMap
字典中,由上代码能够发现这字典的用处。
先看看这个接口的源代码
public interface IAuthorizationHandlerContextFactory { AuthorizationHandlerContext CreateContext(IEnumerable<IAuthorizationRequirement> requirements, ClaimsPrincipal user, object resource); }
接口定义了一个惟一的方法CreateContext
,做用在于建立受权上下文AuthorizationHandlerContext
对象。接口默认实现方式
public class DefaultAuthorizationHandlerContextFactory : IAuthorizationHandlerContextFactory { public virtual AuthorizationHandlerContext CreateContext(IEnumerable<IAuthorizationRequirement> requirements, ClaimsPrincipal user, object resource) { return new AuthorizationHandlerContext(requirements, user, resource); } }
再来看看AuthorizationHandlerContext
受权上下文对象,能够看出,上下文中主要包括用户的Claims和受权策略的要求Requirements
public class AuthorizationHandlerContext { private HashSet<IAuthorizationRequirement> _pendingRequirements; private bool _failCalled; private bool _succeedCalled; public AuthorizationHandlerContext( IEnumerable<IAuthorizationRequirement> requirements, ClaimsPrincipal user, object resource) { if (requirements == null) { throw new ArgumentNullException(nameof(requirements)); } Requirements = requirements; User = user; Resource = resource; _pendingRequirements = new HashSet<IAuthorizationRequirement>(requirements); } public virtual IEnumerable<IAuthorizationRequirement> Requirements { get; } public virtual ClaimsPrincipal User { get; } public virtual object Resource { get; } public virtual IEnumerable<IAuthorizationRequirement> PendingRequirements { get { return _pendingRequirements; } } public virtual bool HasFailed { get { return _failCalled; } } public virtual bool HasSucceeded { get { return !_failCalled && _succeedCalled && !PendingRequirements.Any(); } } public virtual void Fail() { _failCalled = true; } public virtual void Succeed(IAuthorizationRequirement requirement) { _succeedCalled = true; _pendingRequirements.Remove(requirement); } }
所以,在下面咱们恰好会提到了IAuthorizationHandlerProvider
中的方法,能够根据受权上下文获取到请求调用的处理程序。
这个是接口的方法,做用是获取全部的受权Handler
public interface IAuthorizationHandlerProvider { Task<IEnumerable<IAuthorizationHandler>> GetHandlersAsync(AuthorizationHandlerContext context); }
根据以前提到的受权上下文做为GetHandlersAsync
方法参数对象来提取IAuthorizationHandler
对象。
默认接口的实现为DefaultAuthorizationHandlerProvider
, 处理程序的默认实现,为受权请求提供IAuthorizationHandler
public class DefaultAuthorizationHandlerProvider : IAuthorizationHandlerProvider { private readonly IEnumerable<IAuthorizationHandler> _handlers; public DefaultAuthorizationHandlerProvider(IEnumerable<IAuthorizationHandler> handlers) { if (handlers == null) { throw new ArgumentNullException(nameof(handlers)); } _handlers = handlers; } public Task<IEnumerable<IAuthorizationHandler>> GetHandlersAsync(AuthorizationHandlerContext context) => Task.FromResult(_handlers); }
从默认实现的方式能够看出,利用构造函数的方式注入默认的IAuthorizationHandler
的对象,可是咱们再看看接口的实现方法能够发现,GetHandlersAsync
返回的IAuthorizationHandler
对象并非从给定的AuthorizationHandlerContext
上下文中获取的,而是直接经过构造函数的方式注入获得的。
这个时候,你可能会问,那么IAuthorizationHandler
是在哪里注入的呢?
对应下面的 IAuthorizationHandler
由DefaultAuthorizationService
中的受权方法过程调用了
var result = _evaluator.Evaluate(authContext);
IAuthorizationEvaluator
接口,来肯定受权结果是否成功。
public interface IAuthorizationEvaluator { AuthorizationResult Evaluate(AuthorizationHandlerContext context); }
IAuthorizationEvaluator
的惟一方法Evaluate
,该方法会根据以前提供的受权上下文返回一个表示受权成功的AuthorizationResult
对象。默认实现为DefaultAuthorizationEvaluator
public class DefaultAuthorizationEvaluator : IAuthorizationEvaluator { public AuthorizationResult Evaluate(AuthorizationHandlerContext context) => context.HasSucceeded ? AuthorizationResult.Success() : AuthorizationResult.Failed(context.HasFailed ? AuthorizationFailure.ExplicitFail() : AuthorizationFailure.Failed(context.PendingRequirements)); }
由默认实现能够看出,AuthorizationHandlerContext
对象的HasSucceeded
属性决定了受权是否成功。当验证经过时,受权上下文中的HasSucceeded
才会为True。
其中的AuthorizationResult
和AuthorizationFailure
分别为
public class AuthorizationResult { private AuthorizationResult() { } public bool Succeeded { get; private set; } public AuthorizationFailure Failure { get; private set; } public static AuthorizationResult Success() => new AuthorizationResult { Succeeded = true }; public static AuthorizationResult Failed(AuthorizationFailure failure) => new AuthorizationResult { Failure = failure }; public static AuthorizationResult Failed() => new AuthorizationResult { Failure = AuthorizationFailure.ExplicitFail() }; }
public class AuthorizationFailure { private AuthorizationFailure() { } public bool FailCalled { get; private set; } public IEnumerable<IAuthorizationRequirement> FailedRequirements { get;private set; } public static AuthorizationFailure ExplicitFail() => new AuthorizationFailure { FailCalled = true, FailedRequirements = new IAuthorizationRequirement[0] }; public static AuthorizationFailure Failed(IEnumerable<IAuthorizationRequirement> failed) => new AuthorizationFailure { FailedRequirements = failed }; }
这里的两个受权结果 正是IAuthorizationService
进行实现受权AuthorizeAsync
来完成校验返回的结果。
接口方式实现,判断是否受权,实现此接口的类
public interface IAuthorizationHandler { Task HandleAsync(AuthorizationHandlerContext context); }
若是容许受权,可经过此接口的方法来决定是否容许受权。
以前咱们还介绍到,咱们定义的Requirement,能够直接实现
IAuthorizationHandler
接口,也能够单独定义Handler,可是须要注册到DI系统中去。在默认的AuthorizationHandlerProvider中,会从DI系统中获取到咱们注册的全部Handler,最终调用其
HandleAsync
方法。咱们在实现
IAuthorizationHandler
接口时,一般是继承自AuthorizationHandler
来实现,它有以下定义: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); }如上,首先会在
HandleAsync
过滤出与Requirement对匹配的Handler,而后再调用其HandleRequirementAsync
方法。那咱们定义的直接实现
IAuthorizationHandler
了接口的Requirement又是如何执行的呢?
咱们能够发现,IAuthorizationHandler
在AddAuthorization
拓展方法中能够看到默认注册了一个PassThroughAuthorizationHandler
默认实现为:
public class PassThroughAuthorizationHandler : IAuthorizationHandler { public async Task HandleAsync(AuthorizationHandlerContext context) { foreach (var handler in context.Requirements.OfType<IAuthorizationHandler>()) { await handler.HandleAsync(context); } } }
它负责调用该策略中全部实现了IAuthorizationHandler
接口的Requirement
。经过接口实现的方法能够看出,当PassThroughAuthorizationHandler
对象的HandleAsync
方法被执行的时候,它会从AuthroizationHanderContext
的Requirements
属性中提取全部的IAuthoizationHandler
对象,并逐个调用它们的HandleAsync
方法来实施受权检验。
因此能够看到的出,PassThroughAuthorizationHandler
是一个特殊而且重要的受权处理器类型,其特殊之处在于它并无实现针对某个具体规则的受权检验,可是AuthorizationHandlerContext上下文全部的IAuthorizationHandler
都是经过该对象驱动执行的。
接口的方式实现,为特定需求类型调用的受权处理程序的基类
public interface IPolicyEvaluator { Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context); Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource); }
定义了两个方法AuthenticateAsync
和AuthorizeAsync
方法
IPolicyEvaluator
的默认实现为PolicyEvaluator
public class PolicyEvaluator : IPolicyEvaluator { private readonly IAuthorizationService _authorization; public PolicyEvaluator(IAuthorizationService authorization) { _authorization = authorization; } public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context) { if (policy.AuthenticationSchemes != null && policy.AuthenticationSchemes.Count > 0) { ClaimsPrincipal newPrincipal = null; foreach (var scheme in policy.AuthenticationSchemes) { var result = await context.AuthenticateAsync(scheme); if (result != null && result.Succeeded) { newPrincipal = SecurityHelper.MergeUserPrincipal(newPrincipal, result.Principal); } } if (newPrincipal != null) { context.User = newPrincipal; return AuthenticateResult.Success(new AuthenticationTicket(newPrincipal, string.Join(";", policy.AuthenticationSchemes))); } else { context.User = new ClaimsPrincipal(new ClaimsIdentity()); return AuthenticateResult.NoResult(); } } return (context.User?.Identity?.IsAuthenticated ?? false) ? AuthenticateResult.Success(new AuthenticationTicket(context.User, "context.User")) : AuthenticateResult.NoResult(); } public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource) { if (policy == null) { throw new ArgumentNullException(nameof(policy)); } var result = await _authorization.AuthorizeAsync(context.User, resource, policy); if (result.Succeeded) { return PolicyAuthorizationResult.Success(); } // If authentication was successful, return forbidden, otherwise challenge return (authenticationResult.Succeeded) ? PolicyAuthorizationResult.Forbid() : PolicyAuthorizationResult.Challenge(); } }
受权中间件委托它来实现身份验证和受权处理,它内部会调用AuthorizationService,进而执行全部受权处理器AuthorizationHandler, (在后面会提到受权中间件用到这两个方法)
当受权策略没有设置AuthenticationSchemes,则只判断下当前请求是否已作身份验证,若作了就返回成功
当受权策略设置了AuthenticationSchemes,则遍历身份验证方案逐个进行身份验证处理 。
其中context.User
就是使用context.AuthenticateAsync(DefaultAuthenticateScheme)
来赋值的,将全部获得的用户标识重组成一个复合的用户标识。
当咱们但愿使用非默认的Scheme,或者是想合并多个认证Scheme的Claims时,就须要使用基于Scheme的受权来重置Claims了。
它的实现也很简单,直接使用咱们在受权策略中指定的Schemes来依次调用认证服务的
AuthenticateAsync
方法,并将生成的Claims合并,最后返回咱们熟悉的AuthenticateResult
认证结果。
该方法会根据Requirements来完成受权,具体的实现是经过调用IAuthorizationService
调用AuthorizeAsync
来实现的。
最终返回的是一个PolicyAuthorizationResult
对象,并在受权失败时,根据认证结果来返回Forbid(未受权)
或Challenge(未登陆)
。
以上汇总
- 受权服务IAuthorizationService,接口的默认实现为DefaultAuthorizationService,进行受权验证。
- 在会根据受权策略提供器
IAuthorizationPolicyProvider
来获取指定名称的受权。- 经过受权处理器上下文对象工厂IAuthorizationHandlerContextFactory受权处理器AuthorizationHandler在受权时须要传入AuthorizationHandlerContext(上面说了受权完成后的结果也存储在里面)。因此在执行受权处理器以前须要构建这个上下文对象,就是经过这个工厂构建的,主要的数据来源就是 当前 或者 指定的 受权策略AuthorizationPolicy。
- 因此这个时候会受权处理提供其 IAuthorizationHandlerProvider,来获取系统中全部受权处理器。
- 受权评估器IAuthorizationEvaluator来肯定受权结果是否成功,在受权处理器AuthorizationHandler在执行完受权后,结果是存储在AuthorizationHandlerContext中的,这里的评估器只是根据AuthorizationHandlerContext建立一个受权结果AuthorizationResult。
- 上面所说的受权处理器就是IAuthorizationHandler,处理器中包含主要的受权逻辑,在处理的过程当中会将全部的受权处理器一一验证。
- 因此在受权中间件中会利用IPolicyEvaluator中实现的身份认证和受权处理方法来调用AuthorizationService来执行全部的处理器。
在Configure中注册管道:运行使用调用方法来配置Http请求管道
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); //开启认证受权 app.UseAuthentication(); app.UseAuthorization(); }
在这里使用了受权中间件来检查受权,来看看中间件的源码AuthorizationMiddleware
public class AuthorizationMiddleware { // Property key is used by Endpoint routing to determine if Authorization has run private const string AuthorizationMiddlewareInvokedWithEndpointKey = "__AuthorizationMiddlewareWithEndpointInvoked"; private static readonly object AuthorizationMiddlewareWithEndpointInvokedValue = new object(); private readonly RequestDelegate _next; private readonly IAuthorizationPolicyProvider _policyProvider; public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider) { _next = next ?? throw new ArgumentNullException(nameof(next)); _policyProvider = policyProvider ?? throw new ArgumentNullException(nameof(policyProvider)); } public async Task Invoke(HttpContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var endpoint = context.GetEndpoint(); if (endpoint != null) { context.Items[AuthorizationMiddlewareInvokedWithEndpointKey] = AuthorizationMiddlewareWithEndpointInvokedValue; } var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>(); var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData); if (policy == null) { await _next(context); return; } var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>(); var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, context); // Allow Anonymous skips all authorization if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null) { await _next(context); return; } // Note that the resource will be null if there is no matched endpoint var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, context, resource: endpoint); if (authorizeResult.Challenged) { if (policy.AuthenticationSchemes.Any()) { foreach (var scheme in policy.AuthenticationSchemes) { await context.ChallengeAsync(scheme); } } else { await context.ChallengeAsync(); } return; } else if (authorizeResult.Forbidden) { if (policy.AuthenticationSchemes.Any()) { foreach (var scheme in policy.AuthenticationSchemes) { await context.ForbidAsync(scheme); } } else { await context.ForbidAsync(); } return; } await _next(context); } }
进行代码分解:
var endpoint = context.GetEndpoint();
endpoint
的时候,会经过终结点拿到关联的IAuthorizeData
集合var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();
IAuthorizeData
集合调用AuthorizationPolicy.CombineAsync()来建立组合策略(具体了能够看一下上一章) ( 用例: [Authorize(Policy = "BaseRole")] )var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData);
IPolicyEvaluator
获取策略评估器对获得的组合策略进行身份验证,多种身份验证获得的用户证件信息会合并进HttpContext.Uservar policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>(); var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, context);
[AllowAnonymous]
的时候,则直接跳过受权检验。if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null) { await _next(context); return; }
IPolicyEvaluator
提供的AuthorizeAsync
受权检查方法,进行策略受权检查。var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, context, resource: endpoint);
当受权评估拒绝就直接调用身份验证方案进行拒绝。
if (authorizeResult.Challenged) { if (policy.AuthenticationSchemes.Any()) { foreach (var scheme in policy.AuthenticationSchemes) { await context.ChallengeAsync(scheme); } } else { await context.ChallengeAsync(); } return; } else if (authorizeResult.Forbidden) { if (policy.AuthenticationSchemes.Any()) { foreach (var scheme in policy.AuthenticationSchemes) { await context.ForbidAsync(scheme); } } else { await context.ForbidAsync(); } return; }
整个过程当中,受权中间件会调用受权服务IAuthorizationService
来进行受权处理
IAuthorizationService
来实现的,而咱们进行使用只须要提供受权策略的Requirement,很是方便灵活的使用。