我们正在为 .Net Core api 使用一些自定义模型绑定程序,并且模型绑定程序中有一些逻辑,有时会导致我们的 api 返回
403
。
我知道当模型绑定失败时,您可以使用
Mvc.ModelBinding.ModelBindingResult.Failed()
返回 400
,但是如果由于尝试 Unauthorized
访问而失败,那么我们需要返回 403
,最好带有自定义消息。
可以在您的
bindingContext.ModelState.AddModelError("Unauthorized", "Reason")
实现中调用 ModelBinder
。
然后在控制器内部,您可以使用
if(ModelState.IsValid)
来断言 ModelBinder 是否正常工作 以及 如果在此过程中出现任何验证错误。
在您的情况下,您可以检查它是否无效有效,并像平常一样处理控制器中未经授权的响应。
我会为模型绑定中非预期的灾难性错误(例如由格式错误的请求引起)保留
ModelBindingResult.Failed()
,而不是开发人员期望的预期行为。
不能直接返回状态码吗?您可以在那里附加您自己的消息。
return StatusCode(403);
最终我们决定使用
ModelBindingResult.Failed()
和一条自定义错误消息,表明失败是由于授权失败造成的。
就我而言,我想强制执行身份验证,而不依赖于开发人员添加新的控制器入口点而忘记检查
modelState.IsValid
为了实现此目的,我从模型绑定器中抛出一个类型化异常
NotAuthenticatedForThisService
,并使用中间件捕获该异常并返回 403:
// in program.cs
app.UseMiddleware<NotAuthenticatedForServiceExceptionMiddleware>();
public partial class NotAuthenticatedForServiceExceptionMiddleware
{
private readonly RequestDelegate _next;
public NotAuthenticatedForServiceExceptionMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (NotAuthenticatedForThisService)
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
await context.Response.WriteAsync("");
}
}
}