为什么 HttpRequestValidationException 有 500 个 http 错误代码而不是 400

本文关键字:错误代码 http HttpRequestValidationException 为什么 | 更新日期: 2023-09-27 18:32:19

当我基于 MVC5 测试我的 Web 应用程序时,我发现HttpRequestValidationExceptionGetHttpCode() 返回 500 。
我在对服务器请求进行安全测试期间捕获此异常。MVC 执行请求验证并抛出此异常,我在Application_Error中处理了它并返回了 500 个代码,但实际上,如果用户将错误的输入传递给服务器,我应该返回 400 错误(错误请求)。所以不明白为什么异常有 500 错误。我错在哪里?

为什么 HttpRequestValidationException 有 500 个 http 错误代码而不是 400

500被认为

更合适的原因有四个。

  1. 一是不清楚什么时候发生HttpRequestValidationException谁做了错事。可能是用户非常明显地发送了不正确的内容,但也有可能服务器错误地拒绝了完全正常的东西。考虑到这是许多可能是恶意请求的默认行为,因此大多数情况下,它为响应非恶意请求而抛出(用户没有主动尝试对网站造成伤害)可能属于这一类。因此,它可能应该是应该考虑 4xx 或 5xx 的东西,5xx 是一个很好的假设(当你不确定这是客户的错时,不要责怪客户)。

  2. 当它发生在非恶意的情况下时,它通常需要开发人员的关注,这有时只适用于 4xx 代码(404 可能需要开发人员注意,因为 404 是由同一站点上的错误链接引起的,但可能不是)。从 500 个回复中获得的反馈类型更合适。

  3. 通用模型 ASP.NET 开始时几乎将所有异常映射到 500 个响应,这在很多时候确实有意义。MVC 已(明智地)将其替换为映射到其他错误条件的更多异常,但HttpRequestValidationException早于 MVC。

现在这些观点,我不能说我同意其中任何一个。我仍然会说HttpRequestValidationException意味着客户端错误,如果它被错误地识别为这样,那么它仍然被识别为这样,所以它显然是 400。

但是,最后一个原因是:

    虽然 RFC 7231
  1. 中对 400 状态的描述似乎非常清楚地涵盖了此类请求,但 RFC 7231 于 2014 年发布。 HttpRequestValidationException及其处理至少可以追溯到 2003 年,当时 RFC 2616 是相关的 RFC。在该 RFC 中对 400 的描述下,400 可以理解为仅与实际 HTTP 消息格式不正确的请求有关。虽然有些人确实更普遍地使用400作为包罗万象的"客户做错了什么"的回应,但并不完全清楚这样做是否正确。

即便如此,这也给出了一个理由,为什么500在1.5年前可能是一个更合适的反应,而不是为什么它应该保留。更改它会产生向后兼容性影响,因此可能不是一个好主意。

不过,如果您正在编写的给定应用程序有意识地使用HttpRequestValidationException(而不是完全覆盖使用不同方法的验证),那么捕获此类异常并发送 400 而不是 500 是明智的。

这就是 MVC 对待HttpRequestValidationException的方式,我也不喜欢它,但您可以手动将其更改为BadRequest

protected void Application_Error()
{
    var lastError = Server.GetLastError();
    if (lastError is ArgumentException || lastError is HttpRequestValidationException)
    {
        Server.ClearError();
        Response.StatusCode = (int) HttpStatusCode.BadRequest;
    }
}