学习:《asp.net core 3.x 授权中的概念》《asp.net core 3.x 授权默认流程》

--------------------------------------------------------------------------------------------------------

在 Controller 中可以这样标注特性  /*注意,这里的名字取决于你添加AuthenticationHandler时的名字*/

[ApiController]
[Route("api/[controller]")]
public class ValueController : ControllerBase
{
[Authorize(AuthenticationSchemes ="jwtxxx", Policy ="role-policy")]
     //[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]  
     [HttpPost]
     public async Task<IActionResult> Test()
}

--------------------------------------------------------------------------------------------------------

app.UseAuthorization 是Aspnet Core 3.X 的启动 Startup 的配置授权中间件。

提示:授权 Authorization 与身份验证(Scheme)、endpoint 路由(元属性)有关联!

官方定义:https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.authorizationappbuilderextensions.useauthorization?view=aspnetcore-3.1

                  https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authorization.authorizationmiddleware?view=aspnetcore-3.1

 Github 库源代码如下:

public static class AuthorizationAppBuilderExtensions
{
     public static IApplicationBuilder UseAuthorization(this IApplicationBuilder app)
    {
        if (app == null)
        {
          throw new ArgumentNullException(nameof(app));
        }

        VerifyServicesRegistered(app);

        return app.UseMiddleware<AuthorizationMiddleware>();
    }

    private static void VerifyServicesRegistered(IApplicationBuilder app)
    {
            // 在调用 UseAuthorization 之前校验 AddAuthorizationPolicy 
            // 用 AuthorizationPolicyMarkerService 以保证所有 services  被 added.
    if (app.ApplicationServices.GetService(typeof(AuthorizationPolicyMarkerService)) == null)
    {
          throw new InvalidOperationException(Resources.FormatException_UnableToFindServices(
                    nameof(IServiceCollection),
                    nameof(PolicyServiceCollectionExtensions.AddAuthorization),
                    "ConfigureServices(...)"));
    }
}

------------------   AuthorizationMiddleware  的源代码:

https://github.com/dotnet/aspnetcore/blob/b56f84131af2e1ece61241a016e191f5f2fe3fc0/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs

 

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)
         {
              // 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
          var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();
          var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData);
          if (policy == null)
          {
              await _next(context);
              return;
          }

           // Policy evaluator has transient lifetime so it fetched from request services instead of injecting in constructor
           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.Count > 0)
                    {
                         foreach (var scheme in policy.AuthenticationSchemes)
                        {
                             await context.ChallengeAsync(scheme);
                        }
                    }
                   else
                   {
                         await context.ChallengeAsync();
                   }

                    return;
           }
           else if (authorizeResult.Forbidden)
           {
                if (policy.AuthenticationSchemes.Count > 0)
                {
                      foreach (var scheme in policy.AuthenticationSchemes)
                      {
                            await context.ForbidAsync(scheme);
                      }
                }
                else
                {
                      await context.ForbidAsync();
                }

                return;
           }   

           await _next(context);
      } 
}

 

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
  [Route("api/[controller]")]
  [ApiController]
  public class ValueController : ControllerBase