【问题标题】:How can I get route attributes dotnet core 3?如何获取路由属性 dotnet core 3?
【发布时间】:2019-07-30 10:45:55
【问题描述】:

我已将 dotnet core 2.2 升级到 3.preview 7。
所以在那之后,我无法获得自定义属性。
2.2 版中的context.ResourceAuthorizationFilterContext 的类型,但在版本3 中是Microsoft.AspNetCore.Http.Endpoint 的类型。

现在我无法从端点获取属性。

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Gamma.Core.Security
{
    public abstract class AttributeAuthorizationHandler<TRequirement,     TAttribute>
    : AuthorizationHandler<TRequirement> where TRequirement
    : IAuthorizationRequirement where TAttribute : Attribute
    {
        Microsoft.AspNetCore.Http.IHttpContextAccessor _httpContextAccessor = null;
        public AttributeAuthorizationHandler(Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement)
        {
            var attributes = new List<TAttribute>();

            var action = (context.Resource as AuthorizationFilterContext)?.ActionDescriptor as ControllerActionDescriptor;
            if (context.Resource is Microsoft.AspNetCore.Http.Endpoint endpoint)
            {
                //endpoint.
            }

            if (action != null)
            {
                attributes.AddRange(GetAttributes(action.MethodInfo));
            }

            return HandleRequirementAsync(context, requirement, attributes);
        }

        protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, IEnumerable<TAttribute> attributes);

        private static IEnumerable<TAttribute> GetAttributes(MemberInfo memberInfo)
        {
            return memberInfo.GetCustomAttributes(typeof(TAttribute), false).Cast<TAttribute>();
        }
    }
}

【问题讨论】:

    标签: c# .net-core authorization .net-core-3.0 routedata


    【解决方案1】:

    我能够使用Brian's answer 中的ControllerActionDescriptorAuthorizationHandlerContext 获取.NET Core 3.1 中的自定义属性。

    private IEnumerable<TAttribute> GetAttributes<TAttribute>(AuthorizationHandlerContext authContext)
    {
        if (authContext.Resource is RouteEndpoint routeEndpoint)
        {
            var actionDescriptor = routeEndpoint.Metadata.OfType<ControllerActionDescriptor>().SingleOrDefault();
            var attributes = actionDescriptor?.MethodInfo.GetCustomAttributes(typeof(TAttribute), false).Cast<TAttribute>();
            return attributes;
        }
        
        return null;
    }
    

    【讨论】:

    • 这行得通,但我将AppStoreEntitlementsT 切换为TAttribute,如问题中的示例所示。
    • 谢谢。用更好的通用参数名称更新了答案并修复了属性类型
    【解决方案2】:

    尚未找到答案,但这可能会有所帮助:

    https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-3.0 有一节“在处理程序中访问 MVC 请求上下文”,但这是错误的。

    但是,在“反馈”下,他们的 2 个问题看起来与最有希望的答案相关,将下面的代码添加到 AuthorizationHandler

    这可以访问controllerActionDescriptor,但正如你所见,我查看了各种属性,但没有一个给我当前的路由数据:

    var controllerActionDescriptor = routeEndpoint.Metadata
        .OfType<ControllerActionDescriptor>()
        .SingleOrDefault();
    
    if (controllerActionDescriptor != null)
    {
        var a = controllerActionDescriptor.AttributeRouteInfo;
        var p = controllerActionDescriptor.Parameters;
        var ep = controllerActionDescriptor.EndpointMetadata;
        var r = controllerActionDescriptor.RouteValues;
    }
    

    【讨论】:

      【解决方案3】:

      从 .net 5 开始,上下文为 HttpContext

      GetEndPoint method extension on HttpContext

      protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement)
      {
          if(context is HttpContext httContext){
              var endpoint = context.GetEndPoint();
          } else {
              throw ... // let's see how things will move with next version of .net 
          }
      }
      

      【讨论】:

        【解决方案4】:

        我找到了解决方案,在 ConfigureServices 中将 IHttpContextAccessor 注册到 IOC 中

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        

        然后在AttributeAuthorizationHandler中获取

        public class AccountLoginAuthorizeHandler : AttributeAuthorizationHandler<AccountLoginAuthorizationRequirement, AccountLoginAttribute>
        {
            private readonly IHttpContextAccessor _httpContextAccessor;
            public PermissionAuthorizeHandler(IHttpContextAccessor httpContextAccessor, IZaabeeRedisClient redisClient,
            IOptions<LoginConfig> loginConfig)
            {
                _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
            }
            protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AccountLoginAuthorizationRequirement requirement, IEnumerable<AccountLoginAttribute> attributes)
            {
                if (context.Resource is AuthorizationFilterContext filterContext)
                {
                    var httpContext = _httpContextAccessor.HttpContext;
                    //Do Something
                }
                else
                    //Do Something
        
                context.Succeed(requirement);
                return Task.CompletedTask;
            }
        }
        

        【讨论】:

        • 这会增加不必要的开销。
        猜你喜欢
        • 1970-01-01
        • 2021-09-04
        • 1970-01-01
        • 2020-08-03
        • 2020-11-20
        • 2018-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多