3

我已经将 dotnet core 2.2 升级到 3.preview 7。
所以在那之后,我无法获得自定义属性。
context.Resource在 2.2 版中是类型 of AuthorizationFilterContext,但在版本 3 中是类型 of 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>();
        }
    }
}
4

4 回答 4

3

我能够通过在Brian's answerAuthorizationHandlerContext中使用来获得 .NET Core 3.1 中的自定义属性。ControllerActionDescriptor

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;
}
于 2020-10-07T15:54:36.303 回答
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;
}
于 2019-10-22T12:27:49.497 回答
1

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

GetEndPoint方法扩展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 
    }
}
于 2021-04-15T09:28:18.497 回答
-2

我找到了解决方案,在 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;
    }
}
于 2019-11-04T06:55:01.357 回答