首先一些代码:
builder
.Services
.AddAuthorization(options =>
{
options.AddPolicy("IsLoggedIn", policy =>
{
policy.RequireClaim(StoreApi.Properties.Resources.UserName);
policy.RequireClaim(StoreApi.Properties.Resources.UserID);
});
options.AddPolicy("IsCustomer", policy =>
{
policy.RequireClaim(StoreApi.Properties.Resources.UserType, nameof(Customer));
});
options.AddPolicy("IsAdministrator", policy =>
{
policy.RequireClaim(StoreApi.Properties.Resources.UserType, nameof(Administrator));
});
options.AddPolicy("IsApplication", policy =>
{
policy.RequireClaim(StoreApi.Properties.Resources.UserType, nameof(Application));
});
options.AddPolicy("IsSystem", policy =>
{
policy.RequireClaim(StoreApi.Properties.Resources.UserType, nameof(Application), nameof(Administrator));
});
options.AddPolicy("HasCart", policy =>
{
policy.RequireClaim(StoreApi.Properties.Resources.UserCart);
});
});
我有一堆基于声明的策略,并且声明是在资源中定义的,而有些需要具有特定的值。这些声明来自 JWT 令牌,整个事情是一个简化的网络商店。这些政策运作良好,除了一个问题......
当用户未能满足策略时,他们会收到 403“禁止”消息,但不会解释问题所在。因为我有多个政策,所以我想知道哪个政策失败了。
那么,我如何确保 403 向客户端提供这些额外数据?
我认为您应该根据
this文章实现您自己的
IAuthorizationMiddlewareResultHandler
。
示例:
政策:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("Admin",
policy =>
{
policy.Requirements.Add(new RolesAuthorizationRequirement(new[] { "Admin" }));
policy.Requirements.Add(new ClaimsAuthorizationRequirement("MyClaim", new[] { "Test" }));
});
});
[HttpGet]
[Authorize(Policy = "Admin")]
public async Task<IActionResult> Get() => Ok(true);
定制
IAuthorizationMiddlewareResultHandler
public class MyAuthorizationMiddlewareResultHandler : IAuthorizationMiddlewareResultHandler
{
private readonly AuthorizationMiddlewareResultHandler defaultHandler = new();
public async Task HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy,
PolicyAuthorizationResult authorizeResult)
{
// Fall back to the default implementation.
await defaultHandler.HandleAsync(next, context, policy, authorizeResult);
//Have to write to body after default implementation because is sets Http Code
if (!authorizeResult.Succeeded)
{
string? text = authorizeResult.AuthorizationFailure?.FailedRequirements.Aggregate(new StringBuilder(),
(builder, reason) => builder.Append(reason + Environment.NewLine), builder => builder.ToString());
if (!string.IsNullOrWhiteSpace(text))
await context.Response.Body.WriteAsync(Encoding.UTF8.GetBytes(text));
}
}
}
它的注册
builder.Services.AddSingleton<IAuthorizationMiddlewareResultHandler,
MyAuthorizationMiddlewareResultHandler>();
完成所有这些步骤后,调用端点后的结果将是状态代码 403 的响应:
RolesAuthorizationRequirement:User.IsInRole must be true for one of the following roles: (Admin)
ClaimsAuthorizationRequirement:Claim.Type=MyClaim and Claim.Value is one of the following values: (Test)
如果您想自定义响应文本,您应该使用
FailedRequirements
的 FailureReasons
和 authorizeResult.AuthorizationFailure
属性。
来源: