Xác thực quyền tùy chỉnh trong ASP.NET Core

Để triển khai xác thực quyền tùy chỉnh, cần kế thừa lớp trừu tượng

public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandler where TRequirement : IAuthorizationRequirement

public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandler 
    where TRequirement : IAuthorizationRequirement
{
    protected AuthorizationHandler();
    public virtual Task HandleAsync(AuthorizationHandlerContext context);
    protected abstract Task HandleRequirementAsync(
        AuthorizationHandlerContext context, 
        TRequirement requirement);
}

Triển khai giao diện

IAuthorizationRequirement

public interface IAuthorizationRequirement { }

Lớp xử lý xác thực tùy chỉnh

public class CustomAuthHandler : AuthorizationHandler<AuthRequirement>
{
    private readonly IMemoryCache _cache;
    private readonly IAuthenticationSchemeProvider _schemes;

    public CustomAuthHandler(IAuthenticationSchemeProvider schemes)
    {
        _schemes = schemes;
        _cache = new MemoryCache(Options.Create(new MemoryCacheOptions
        {
            CompactionPercentage = 0.25
        }));

        var permissions = new List<AuthPermission>
        {
            new AuthPermission{ Action = "Get", Controller = "Users", Role = "User" },
            new AuthPermission{ Action = "Update", Controller = "Users", Role = "User" }
        };
        
        _cache.Set("auth_permissions", permissions);
    }

    protected override async Task HandleRequirementAsync(
        AuthorizationHandlerContext context, 
        AuthRequirement requirement)
    {
        var httpContext = context.Resource as HttpContext;
        var actionDescriptor = httpContext.GetEndpoint().Metadata
            .OfType<ControllerActionDescriptor>()
            .FirstOrDefault();

        var authResult = await httpContext.AuthenticateAsync("CustomScheme");
        
        if (!authResult.Succeeded)
        {
            context.Fail();
            return;
        }

        httpContext.User = authResult.Principal;
        var controller = actionDescriptor.ControllerName;
        var action = actionDescriptor.ActionName;
        var username = httpContext.User.FindFirstValue(ClaimTypes.Name);
        var userRole = httpContext.User.FindFirstValue(ClaimTypes.Role);
        
        var permissionList = _cache.Get<List<AuthPermission>>("auth_permissions");
        var hasPermission = permissionList.Any(p => 
            p.Controller == controller && 
            p.Action == action && 
            p.Role == userRole);

        if (hasPermission)
        {
            context.Succeed(requirement);
        }
        else
        {
            if (httpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
            {
                httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            }
            else
            {
                httpContext.Response.Redirect(requirement.AccessDeniedPath);
            }
            context.Fail();
        }
    }
}

Yêu cầu xác thực

public class AuthRequirement : IAuthorizationRequirement
{
    public string AccessDeniedPath { get; }
    public string ClaimType { get; }
    public TimeSpan ExpiryDuration { get; }

    public AuthRequirement(
        string accessDeniedPath, 
        string claimType, 
        TimeSpan expiryDuration)
    {
        AccessDeniedPath = accessDeniedPath;
        ClaimType = claimType;
        ExpiryDuration = expiryDuration;
    }
}

Định nghĩa quyền

public class AuthPermission
{
    public string Role { get; set; }
    public string Controller { get; set; }
    public string Action { get; set; }
}

Đăng ký dịch vụ

var authPolicy = new AuthRequirement(
    accessDeniedPath: "/Home/AccessDenied",
    claimType: ClaimTypes.Name,
    expiryDuration: TimeSpan.FromMinutes(5));

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("CustomPolicy", policy => 
        policy.Requirements.Add(authPolicy));
});

builder.Services.AddSingleton<IAuthorizationHandler, CustomAuthHandler>();

Thẻ: ASP.NET Core authorization IAuthorizationHandler IAuthorizationRequirement Custom Authentication

Đăng vào ngày 25 tháng 6 lúc 07:53