Reputation: 405
I have upgraded dotnet core 2.2 to 3.preview 7.
So after that, I can't get custom attributes.
context.Resource
in version 2.2 was type of AuthorizationFilterContext
, but in version 3 is type of Microsoft.AspNetCore.Http.Endpoint
.
Now I couldn't get attributes from 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>();
}
}
}
Upvotes: 5
Views: 4029
Reputation: 16192
Since .net 5, context is HttpContext
There is 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
}
}
Upvotes: 3
Reputation: 61
I was able to get custom attributes in .NET Core 3.1 from AuthorizationHandlerContext
using ControllerActionDescriptor
in Brian's answer.
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;
}
Upvotes: 6
Reputation: 11
I have found a solution,in ConfigureServices register an IHttpContextAccessor into IOC
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
then get it in 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;
}
}
Upvotes: -2
Reputation: 164
Not found the answer yet, but this might help:
https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-3.0 has a section "Accessing MVC request context in handlers", but this is wrong.
However under "Feedback" theirs 2 questions that look relevant with the most promising answer saying to add the code below to the AuthorizationHandler
.
This gives access to controllerActionDescriptor
, but as you can see I have looked at various property's but none give me the current routing data:
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;
}
Upvotes: 2