首页 > 编程语言 >ASP.NET Core 授权中间件 AuthorizationMiddleware

ASP.NET Core 授权中间件 AuthorizationMiddleware

时间:2023-07-27 16:44:35浏览次数:45  
标签:Core ASP resource 中间件 policy context var public authorization

  /// <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; }

 




标签:Core,ASP,resource,中间件,policy,context,var,public,authorization
From: https://www.cnblogs.com/871735097-/p/17585254.html

相关文章

  • .net core 调用打印机打印pdf文件 FreeSpire.PDF
    首先,参考了https://stackoverflow.com/questions/63941980/is-it-possible-to-print-documents-from-a-net-core-3-1-windows-service中的说明,声明:我用的是core3.1测试的先下载了FreeSpire.PDF的NuGet包,可以看出来简介上是支持print的: 然后我的测试直接在controller中:1[......
  • 使用ASP.NET Core Minimal API和MailKit发送电子邮件
    步骤1:创建新项目通过以下命令在终端中创建一个新的ASP.NETCoreWebAPI项目:dotnetnewwebapi-oSendingEmail由于我们正在使用MinimalAPIs,因此删除不必要的Controller文件夹和WeatherForecast类。步骤2:定义电子邮件数据传输对象(DTO)为了将数据从我们的API传递到邮件服务......
  • .NET Core依赖注入与Autofac注入介绍
    0前言本文主要介绍了ASP.NETCore自带的依赖注入框架的用法,然后针对原生框架的不足,介绍了更加完备的autofac框架的集成和使用。1.NETCore原生DI框架.NetCore自带一个依赖注入的框架,使用起来很是方便,不多说,先从简单示例做起。1.1简单示例以ASP.NETCoreweb的API项目为例......
  • 33构件与中间件的基本概念
    构件的定义:是一种组装单元,具有规范的接口规约和显式的语境依赖。软件构件可以被独立地部署并由第三方任意组装定义2:有价值、几乎独立并可替换的一个部分,有清晰的功能定义3:是一个独立发布的功能,可以通过接口访问服务 模块的特性:结构化开发的产物对象的特性:具有唯一标志、有状......
  • 34中间件
    中间件的分类:通信处理(消息)中间件:可靠、高效、实时跨平台通信,elink,MQSeries事务处理(交易)中间件:事务分发、负载均衡数据存取管理中间件:虚拟缓冲存取web服务器中间件:有负载均衡安全中间件:加密,认证跨平台和架构的中间件:解决跨平台问题专用平台中间件:为特定应用领域设计的领域......
  • asp.net core之Host
    Host简介在ASP.NETCore中,Host是一个托管应用程序的宿主环境。它提供了一种统一的方式来启动和运行应用程序,无论是在开发环境中还是在生产环境中。Host负责处理应用程序的生命周期、配置和依赖项管理等任务,使开发人员能够专注于应用程序的业务逻辑。Host是通过使用IHostBuilder......
  • 消息中间件 MQ 企业级方案设计
    第1部分:异步通信与负载均衡 引言WebsphereMQ是IBM功能强大的消息传送中间件产品,它以其成熟的技术和世界领先的产品向我们提供了的功能丰富、可靠易用的异构平台间实现可靠信息传递的成熟解决方案。使用MQ消息传递产品可以帮助业务应用在不同种类平台上交换信息,以消......
  • ASP.NET Core Identity 系列之一
    ASP.NETCoreIdentity提供给我们一组工具包和API,它能帮助我们应用程序创建授权和认证功能,也可以用它创建账户并使用用户名和密码进行登录,同时也提供了角色和角色管理功能。ASP.NETCoreIdentity使用SQLServer/第三方数据库存储用户名和密码,角色和配置数据这系列中我们主要使用......
  • ASP.NET Core Identity 系列之一
    ASP.NETCoreIdentity提供给我们一组工具包和API,它能帮助我们应用程序创建授权和认证功能,也可以用它创建账户并使用用户名和密码进行登录,同时也提供了角色和角色管理功能。ASP.NETCoreIdentity使用SQLServer/第三方数据库存储用户名和密码,角色和配置数据这系列中我们主要使用VS......
  • Asp.Net 使用Log4Net (封装帮助类)
    Asp.Net使用Log4Net(封装帮助类)1.创建Log4Net帮助类首先,在你的项目中创建一个Log4Net帮助类,用于封装Log4Net的配置和日志记录逻辑。usinglog4net;usinglog4net.Config;publicclassLogHelper{privatestaticreadonlyILoglog=LogManager.GetLogger(typeof(......