“context.Resource as AuthorizationFilterContext” returning null in ASP.NET Core 3.0

前端 未结 6 535
情书的邮戳
情书的邮戳 2020-12-16 07:50

I am trying to implement a custom authorization requirement following a tutorial. It seems like context.Resource no longer contains AuthorizationFilterCo

6条回答
  •  北海茫月
    2020-12-16 08:11

    This is due to the new endpoint routing in .NET Core 3.0.

    To quote the below ticket.

    This is because when using endpoint routing in ASP.NET Core 3.0:

    Mvc will no longer add AuthorizeFilter to ActionDescriptor and ResourceInvoker will not call AuthorizeAsync() https://github.com/aspnet/AspNetCore/blob/90ab2cb965aeb8ada13bc4b936b3735ca8dd28df/src/Mvc/Mvc.Core/src/ApplicationModels/AuthorizationApplicationModelProvider.cs#L40

    Mvc will add all Filter as metadata to endpoint.Metadata https://github.com/aspnet/AspNetCore/blob/5561338cfecac5ca4b1dda2f09a7f66153d0b5fe/src/Mvc/Mvc.Core/src/Routing/ActionEndpointFactory.cs#L348

    instead by AuthorizationMiddleware call the AuthorizeAsync() and resouorce is Endpoint https://github.com/aspnet/AspNetCore/blob/5561338cfecac5ca4b1dda2f09a7f66153d0b5fe/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs#L63

    New method.

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CookieOrTokenAuthorizationRequirement requirement)
    {
        if (context.Resource is Endpoint endpoint)
        {
            if (endpoint.Metadata.OfType().Any(filter => filter is MyFilter))
            {
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
        }
    }
    

    https://github.com/dotnet/aspnetcore/issues/11075

    It's worth noting too that using the new context you won't be able to access route data as you were before with the AuthorizationFilterContext. You will need to inject an IHttpContextAccessor into the AuthorizationHandler.

    // Ensure your handler is registered as scoped
    services.AddScoped();
    
    
    public class InvestorRequirementHandler : AuthorizationHandler
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
    
        public InvestorRequirementHandler(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }
    
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, InvestorRequirement requirement)
        {
            var tenant = httpContextAccessor.HttpContext.GetRouteData().Values[ExceptionHandlerMiddleware.TenantCodeKey].ToString();
        }
    }
    

提交回复
热议问题