我已经使用 ExceptionHandler 实现了它。我想保留 403 状态码,但要自定义错误消息。所以我创建了自定义异常:
public class ForbiddenException : BaseException
{
public ForbiddenException(string message) : base(HttpStatusCode.Forbidden, message)
{
}
public ForbiddenException(string message, object info) : base(HttpStatusCode.Forbidden, message, info)
{
}
}
public abstract class BaseException : Exception
{
protected BaseException(HttpStatusCode httpErrorCode, string message, Exception innerException = null) : base(message,
innerException)
{
HttpErrorCode = httpErrorCode;
}
protected BaseException(HttpStatusCode httpErrorCode, string message, object info, Exception innerException = null) :
this(httpErrorCode,
message, innerException)
{
Info = info;
}
public HttpStatusCode HttpErrorCode { get; set; }
public object Info { get; set; }
}
然后在 AuthorizationHandler 里面我抛出了这个异常:
public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
List<Claim> userPermissionsClaims =
context.User.Claims.Where(c => c.Type == PermissionConstants.PermissionClaimType).ToList();
if (userPermissionsClaims.Any(pc => requirement.Permissions.Any(p => (Permissions)Convert.ToInt16(pc.Value) == p)))
{
context.Succeed(requirement);
}
else
{
throw new ForbiddenException(string.Format(ErrorMessages.PermissionsRequired, string.Join(", ", requirement.Permissions)));
}
return Task.CompletedTask;
}
}
这是一个全局异常处理程序:
app.UseExceptionHandler(exceptionHandler =>
{
exceptionHandler.Run(async context =>
{
await HandleException(context.Features.Get<IExceptionHandlerFeature>().Error, context, env);
});
});
public async Task HandleException(Exception exception, HttpContext context)
{
var message = exception?.Message;
if (exception is BaseException)
{
context.Response.StatusCode = (int)(exception as BaseException)?.HttpErrorCode;
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
await context.Response.WriteAsync(message);
await context.Response.CompleteAsync();
}