ASP.NET Core 授权中间件 AuthorizationMiddleware

  /// <summary>
  /// A middleware that enables authorization capabilities.
  /// </summary>
  public class AuthorizationMiddleware
  {
      // AppContext switch used to control whether HttpContext or endpoint is passed as a resource to AuthZ
      private
      const string SuppressUseHttpContextAsAuthorizationResource = "Microsoft.AspNetCore.Authorization.SuppressUseHttpContextAsAuthorizationResource";
      // 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;
      /// <summary>
      /// Initializes a new instance of <see cref="AuthorizationMiddleware"/>.
      /// </summary>
      /// <param name="next">The next middleware in the application middleware pipeline.</param>
      /// <param name="policyProvider">The <see cref="IAuthorizationPolicyProvider"/>.</param>
      public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider)
          {
              _next = next ? ?
                  throw new ArgumentNullException(nameof(next));
              _policyProvider = policyProvider ? ?
                  throw new ArgumentNullException(nameof(policyProvider));
          }
          /// <summary>
          /// Invokes the middleware performing authorization.
          /// </summary>
          /// <param name="context">The <see cref="HttpContext"/>.</param>
      public async Task Invoke(HttpContext context)
      {
          if(context == null)
          {
              throw new ArgumentNullException(nameof(context));
          }        //mvc控制器路由
          var endpoint = context.GetEndpoint();
          if(endpoint != null)
          {
              // EndpointRoutingMiddleware uses this flag to check if the Authorization middleware processed auth metadata on the endpoint.
              // The Authorization middleware can only make this claim if it observes an actual endpoint.
              context.Items[AuthorizationMiddlewareInvokedWithEndpointKey] = AuthorizationMiddlewareWithEndpointInvokedValue;
          }
          // IMPORTANT: Changes to authorization logic should be mirrored in MVC's AuthorizeFilter
          //获取标签 AuthorizeAttribute  中的数据 转化为   IAuthorizeData
                
          var authorizeData = endpoint ? .Metadata.GetOrderedMetadata <IAuthorizeData> () ? ? Array.Empty < IAuthorizeData > ();
          //根据setup.cs 配置的 services.AddAuthorization(options.AddPolicy("Book", policy =>{ policy.Requirements.Add(new BookRequirment());}));
          //如果一个类上面贴了多个  AuthorizeAttribute  ,AuthorizationPolicy.CombineAsync 就会把   Requirements  组合起来
          var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData);
          if(policy == null)
          {
              await _next(context);
              return;
          } // Policy evaluator has transient lifetime so it's fetched from request services instead of injecting in constructor 
          var policyEvaluator = context.RequestServices.GetRequiredService <IPolicyEvaluator> ();
          var authenticateResult = await policyEvaluator.AuthenticateAsync(policy, context);
          if(authenticateResult ? .Succeeded ? ? false)
          {
              if(context.Features.Get <IAuthenticateResultFeature> () is IAuthenticateResultFeature authenticateResultFeature)
              {
                  authenticateResultFeature.AuthenticateResult = authenticateResult;
              }
              else
              {
                  var authFeatures = new AuthenticationFeatures(authenticateResult);
                  context.Features.Set < IHttpAuthenticationFeature > (authFeatures);
                  context.Features.Set < IAuthenticateResultFeature > (authFeatures);
              }
          } // 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;
          }
          object ? resource;
          if(AppContext.TryGetSwitch(SuppressUseHttpContextAsAuthorizationResource, out
                  var useEndpointAsResource) && useEndpointAsResource)
          {
              resource = endpoint;
          }
          else
          {
              resource = context;
          }
          var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult!, context, resource);
          var authorizationMiddlewareResultHandler = context.RequestServices.GetRequiredService <IAuthorizationMiddlewareResultHandler> ();
          await authorizationMiddlewareResultHandler.HandleAsync(_next, context, policy, authorizeResult);
      }
  }
AuthorizationPolicy  对象的数据结构
用于存放endpoint 中设计的 PolicyRequirement 的集合。
   /// <summary>
        /// Gets a readonly list of <see cref="IAuthorizationRequirement"/>s which must succeed for
        /// this policy to be successful.
        /// </summary>
        public IReadOnlyList<IAuthorizationRequirement> Requirements { get; }

        /// <summary>
        /// Gets a readonly list of the authentication schemes the <see cref="AuthorizationPolicy.Requirements"/>
        /// are evaluated against.
        /// </summary>
        public IReadOnlyList<string> AuthenticationSchemes { get; }

 

3  IAuthorizationHandler 的二种方式,   

  public interface IAuthorizationHandler
    {
        /// <summary>
        /// Makes a decision if authorization is allowed.
        /// </summary>
        /// <param name="context">The authorization information.</param>
        Task HandleAsync(AuthorizationHandlerContext context);
    }
services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

/// <summary>
    /// 判断用户是否具有权限
    /// </summary>
    public class PermissionHandler : IAuthorizationHandler
    {
        public async Task HandleAsync(AuthorizationHandlerContext context)
        {
          
        }
    }

第2中方式   

AuthorizationHandler<TRequirement> 抽象类实现了 IAuthorizationHandler,HandleAsync 从context 根据不同的类型的 IAuthorizationRequirement  去执行对应的 RequirementHandler
    public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandler
            where TRequirement : IAuthorizationRequirement
    {
        /// <summary>
        /// Makes a decision if authorization is allowed.
        /// </summary>
        /// <param name="context">The authorization context.</param>
        public virtual async Task HandleAsync(AuthorizationHandlerContext context)
        {
            foreach (var req in context.Requirements.OfType<TRequirement>())
            {
                await HandleRequirementAsync(context, req);
            }
        }

        /// <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 abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement);
    }

 

RequirementHandler 仅实现 抽象类的 HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement) 的方法,接收context 参数和 requirement

 /// <summary>
        /// Checks if a user meets a specific set of requirements for the specified resource.
        /// </summary>
        /// <param name="user">The user to evaluate the requirements against.</param>
        /// <param name="resource">The resource to evaluate the requirements against.</param>
        /// <param name="requirements">The requirements to evaluate.</param>
        /// <returns>
        /// A flag indicating whether authorization has succeeded.
        /// This value is <value>true</value> when the user fulfills the policy otherwise <value>false</value>.
        /// </returns>
        public virtual 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); //找到实现IAuthorizationHandler的对象,包含 直接继承 IAuthorizationHandler或者 requirementHandler, 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(result.Failure!); } return result; }

 




posted @ 2023-07-27 16:34  米姐  阅读(131)  评论(0编辑  收藏  举报