Để 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>();