首页 > 解决方案 > 自定义授权属性 - ASP .NET Core 2.2

问题描述

我想创建一个自定义 Authorize 属性,以便能够在失败时发送个性化响应。有很多例子,但我找不到我要找的东西。注册保单时,我添加了“索赔”。是否可以在自定义属性中访问已注册的声明而无需通过参数传递声明?或者是否有可能知道索赔检查是否发生,如果没有,返回个性化回复?谢谢!

public static void AddCustomAuthorization(this IServiceCollection serviceCollection)
{
    serviceCollection.AddAuthorization(x =>
    {
        x.AddPolicy(UserPolicy.Read,
            currentPolicy => currentPolicy.RequireClaim(UserClaims.Read));
    });
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext authorizationFilterContext)
    {
        if (authorizationFilterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            if (!authorizationFilterContext.HttpContext.User.HasClaim(x => x.Value == "CLAIM_NAME")) // ACCESS TO REGISTER CLAIM => currentPolicy => currentPolicy.RequireClaim(UserClaims.Read)
            {
                authorizationFilterContext.Result = new ObjectResult(new ApiResponse(HttpStatusCode.Unauthorized));
            }
        }
    }
}

[HttpGet]
[CustomAuthorizeAttribute(Policy = UserPolicy.Read)]
public async Task<IEnumerable<UserDTO>> Get()
{
    return ...
}

标签: c#asp.net-core

解决方案


您可以使用IAuthorizationPolicyProvider获取策略,然后使用ClaimsAuthorizationRequirement.ClaimType获取声明名称。而且由于它具有异步 API,因此最好使用IAsyncAuthorizationFilter而不是IAuthorizationFilter. 尝试这个:

public class CustomAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter
{
    public async Task OnAuthorizationAsync(AuthorizationFilterContext authorizationFilterContext)
    {
        var policyProvider = authorizationFilterContext.HttpContext
            .RequestServices.GetService<IAuthorizationPolicyProvider>();
        var policy = await policyProvider.GetPolicyAsync(UserPolicy.Read);
        var requirement = (ClaimsAuthorizationRequirement)policy.Requirements
            .First(r => r.GetType() == typeof(ClaimsAuthorizationRequirement));

        if (authorizationFilterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            if (!authorizationFilterContext.HttpContext
              .User.HasClaim(x => x.Value == requirement.ClaimType))
            {
                authorizationFilterContext.Result = 
                   new ObjectResult(new ApiResponse(HttpStatusCode.Unauthorized));
            }
        }
    }
}

推荐阅读