排查 IIS 中的 HTTP 400 错误

适用于: Internet Information Services

本文介绍使用 IIS 时识别各种 HTTP 400 错误的原因的故障排除步骤。

概述

HTTP 客户端(如 Microsoft Edge)向 IIS 服务器发送 HTTP 请求后,可能会显示以下类型的错误消息:

HTTP 400 - 请求错误

在此方案中,IIS 拒绝客户端的 HTTP 请求,因为请求不满足服务器的 HTTP 分析规则,超出时间限制,或者 IIS 或HTTP.sys要求传入请求遵守的某些其他规则失败。 IIS 将 HTTP 400 - Bad Request 状态发送回客户端,然后终止 TCP 连接。

工具

疑难解答方法

对 HTTP 400 条件进行故障排除时,请务必记住,根本问题是客户端已向 IIS 发送了一个请求,该请求会中断HTTP.sys强制执行的一个或多个规则。 考虑到这一点,你将想要查看客户端发送到 IIS 的具体内容。 为此,请捕获发送错误请求的客户端的网络跟踪。 你可以分析此跟踪来查看客户端发送给 IIS 的原始数据,并查看 IIS 发送回客户端的原始响应数据。 还可以使用名为 FiddlerHTTP 探查器工具,这是一个出色的工具,因为它允许你查看 HTTP 标头,即使客户端和服务器通过 SSL 通信也是如此。

使用的下一个数据项是 C:\Windows\System32\LogFiles\HTTPERR\httperr.log 文件。 在 IIS 中,HTTP.sys组件在传入 HTTP 请求传递到 IIS 之前处理传入的 HTTP 请求,并负责阻止不符合 IIS 要求的请求。 当HTTP.sys阻止请求时,它会将信息记录到其 httperr.log 文件中,说明错误的请求及其被阻止的原因。

注意

有关HTTP.sys提供的 HTTP API 错误日志记录的详细信息,请参阅 HTTP API 中的错误日志记录。

从技术上看,客户端可能会收到 HTTP 400 响应,该响应在httperr.log文件中没有关联的日志条目。 如果 ISAPI 筛选器或扩展或 IIS 中的 HTTP 模块设置 400 状态,在这种情况下,可以查看 IIS 日志了解详细信息,则可能发生这种情况。 如果客户端和服务器(如代理服务器或其他网络设备)之间的实体截获来自 IIS 的响应,并用自己的 400 状态和/或“错误的请求”错误替代它,则也可能会发生这种情况。

注意

本文主要讨论访问网站之前常见的 HTTP 400 错误。 在某些情况下,由于自定义代码逻辑或运行时(如 ASP.NET)配置,网站可能会向客户端返回 HTTP 400 错误。 如果在执行以下部分中的步骤后仍无法解决 HTTP 400 错误,请尝试在 IIS 中使用 失败的请求跟踪功能 进行故障排除。 如果发现 HTTP 400 错误实际上是由网站的相应运行时处理程序(如 ASP.NET)设置的,则可能需要检查请求和响应的详细信息以及网站的相关代码逻辑和运行时配置,以了解 HTTP 400 错误的原因。

示例方案

下面是 HTTP 400 方案的一个示例,其中客户端向 IIS 发送错误请求,服务器发送回“HTTP 400 - 错误请求”消息。

客户端发送请求时,返回的浏览器错误如下所示:

错误的请求(标头字段太长)

捕获请求和响应的网络跟踪时,会看到以下输出:

请求:

HTTP: GET Request from Client
HTTP: Request Method =GET
HTTP: Uniform Resource Identifier =/1234567890123456789012345678901234567890/time.asp
HTTP: Protocol Version =HTTP/1.1
HTTP: Accept-Language =en-us
HTTP: UA-cpu =x86
HTTP: Accept-Encoding =gzip, deflate
HTTP: Host =iisserver
HTTP: Connection =Keep-Alive
HTTP: Data: Number of data bytes remaining = 14 (0x000E)

响应:

HTTP: Response to Client; HTTP/1.1; Status Code = 400 - Bad Request
HTTP: Protocol Version =HTTP/1.1
HTTP: Status Code = Bad Request
HTTP: Reason =Bad Request
HTTP: Content-Type =text/html
HTTP: Date =Wed, 14 Nov 2012 20:36:36 GMT
HTTP: Connection =close
HTTP: Content-Length =44
HTTP: Data: Number of data bytes remaining = 63 (0x003F)

你会注意到,响应标头不会像浏览器中的错误消息一样多。 但是,如果查看响应正文中的原始数据,则会看到更多内容:

00000030                                           48 54               HT
00000040 54 50 2F 31 2E 31 20 34 30 30 20 42 61 64 20 52 TP/1.1.400.Bad.R
00000050 65 71 75 65 73 74 0D 0A 43 6F 6E 74 65 6E 74 2D equest..Content-
00000060 54 79 70 65 3A 20 74 65 78 74 2F 68 74 6D 6C 0D Type:.text/html.
00000070 0A 44 61 74 65 3A 20 57 65 64 2C 20 32 38 20 4A .Date:.Wed,.28.J
00000080 61 6E 20 32 30 30 39 20 32 30 3A 33 36 3A 33 36 an.2009.20:36:36
00000090 20 47 4D 54 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E .GMT..Connection
000000A0 3A 20 63 6C 6F 73 65 0D 0A 43 6F 6E 74 65 6E 74 :.close..Content
000000B0 2D 4C 65 6E 67 74 68 3A 20 34 34 0D 0A 0D 0A 3C -Length:.44....<
000000C0 68 31 3E 42 61 64 20 52 65 71 75 65 73 74 20 28 h1>Bad.Request.(
000000D0 48 65 61 64 65 72 20 46 69 65 6C 64 20 54 6F 6F Header.Field.Too
000000E0 20 4C 6F 6E 67 29 3C 2F 68 31 3E 01 02 03 04 05 .Long).....
000000F0 05 06 0E 94 63 D6 68 37 1B 8C 16 FE 3F D5       ....c.h7....?.

你可以看到浏览器中显示的错误消息文本也可在网络跟踪中的原始响应数据中看到。

下一步是查看 C:\Windows\System32\LogFiles\HTTPERR 目录中与错误请求对应的条目的httperr.log文件

#Software: Microsoft HTTP API 1.0
#Version: 1.0
#Date: 2012-11-14 20:35:02
#Fields: date time cs-version cs-method cs-uri sc-status s-reason 
2012-11-14 20:36:36 HTTP/1.1 GET /1234567890/time.asp 400 FieldLength

在此方案中,Reasonhttperr.log 文件中的字段提供了诊断问题所需的确切信息。 你会看到HTTP.sys记录 FieldLength 为此请求失败的原因短语。 了解原因短语后,请检查 HTTP API 日志部分获取其说明的错误类型中的表

FieldLength:超出字段长度限制。

因此,此时,你从浏览器错误消息和 HTTP API 错误日志记录中知道,请求包含其中一个 HTTP 标头中的数据超过了允许的长度限制。 对于此示例,该 HTTP: Uniform Resource Identifier header 长度有目的: /1234567890123456789012345678901234567890/time.asp

本示例故障排除的最后一个阶段是检查 IIS 的HTTP.sys注册表项和默认设置

由于你知道原因短语和错误建议标头字段长度超出限制,因此可以在注册表项表中缩小搜索范围,例如。 在这里,主要候选项是:

注册表项 默认值 有效值范围 注册表项函数 WARNING 代码
MaxFieldLength 16384 64 - 65534 (64k - 2) 字节 为每个标头设置上限。 请参阅 MaxRequestBytes。 对于 URL,此限制转换为大约 3.2 万个字符。 1

为了重现此示例的此错误, MaxFieldLength 注册表项设置为值 2。 由于请求的 URL 具有一个 HTTP: Uniform Resource Identifier header 包含两个以上的字符的字段,因此请求被阻止了 FieldLength 原因短语。

另一种常见的 HTTP 400 方案是发出 HTTP 请求的用户是大量 Active Directory 组的成员,网站配置为用户 Kerberos 身份验证。 出现此方案时,将显示类似于以下情况的错误消息给用户:

错误的请求(请求头过长)

在此方案中,作为客户端 HTTP 请求的一部分包含的身份验证令牌太大,并且超出了强制实施http.sys的大小限制。 HTTP 400 - 错误请求(请求标头过长)响应 HTTP 请求中详细讨论了此问题以及解决方案

参考