我要修改“授权失败”的响应正文(“ 403禁止”)。 我目前收到403错误,但是找不到拦截中间件/过滤器以修改响应正文的正确位置。
我在路线上使用的是AuthorizeAttribute
[Authorize(Roles = Constants.Roles.MyRole)]
public IActionResult GetResources() { /* ... */ }
并设置身份验证。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = services.BuildServiceProvider().GetService<TokenValidationParameters>();
options.Events = new JwtBearerEvents(){
OnChallenge = context => { /* handle authentication errors (401) */ }
OnAuthenticationFailed = context => { /* This never seems to get hit */ }
OnMessageRecieved = context => { /* always hit but authorization not hit yet */ }
OnTokenValidated = context => { /* always hit but authorization not hit yet */ }
};
});
我尝试将要求添加到我的AuthorizeFilter并添加ExceptionFilter。
services.AddMvc(options =>
{
options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddRequirements(new ReturnErrorRequirement())
.Build()));
options.Filters.Add(new MyExceptionFilter());
});
但是,我的ReturnErrorHandler在[AuthorizeAttribute]的处理程序之前被调用,并且异常过滤器根本没有被命中。
无奈之下,我为角色创建了自己的自定义属性和授权处理程序。
[System.AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
sealed class AllowedRoleAttribute : Attribute
{
public AllowedRoleAttribute(string role)
{
Role = role;
}
public string Role
{
get;
}
}
public class RouteAccessHandler : AuthorizationHandler<RouteAccessRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RouteAccessRequirement requirement)
{
//get roles from claims
var roles = context.User.Claims.Where(claim => claim.Type == ClaimTypes.Role).ToList();
//get allowed roles from route method
var authorizationFilterContext = (AuthorizationFilterContext) context.Resource;
var descriptor = (ControllerActionDescriptor) authorizationFilterContext.ActionDescriptor;
var allowedRoles = Attribute.GetCustomAttributes(descriptor.MethodInfo, typeof(AllowedRoleAttribute)).Cast<AllowedRoleAttribute>().ToList();
//determine if we have a match
if (!allowedRoles.Any() || roles.Any(role =>
allowedRoles.Any(allowedRole =>
role.Value == allowedRole.Role)))
{
context.Succeed(requirement);
}
else
{
// Modify response
}
return Task.CompletedTask;
}
}
但是,这感觉像是黑客。
documentation没有任何示例,我的google-fu让我失望了。
如何在授权失败时修改响应正文?