为什么POST请求中的“Content-Length:0”?

时间:2008-11-30 00:59:57

标签: windows internet-explorer http web-applications proxy

客户有时会在提交表单时向Content-Length: 0发送POST请求(10到40多个字段)。

我们使用不同的浏览器和不同的位置对其进行了测试,但无法重现错误。客户正在使用Internet Explorer 7和代理。

我们让他们让他们的系统管理员从他们这边看问题。没有代理等运行一些测试。

与此同时(半年后仍未回答)我很好奇其他人是否知道Content-Length: 0请求有类似问题。也许来自一些Windows网络,里面有大公司的特殊代理。

Internet Explorer 7是否存在已知问题?有代理系统吗? Windows网络本身?

Google仅在NTLM(和此类)身份验证的上下文中显示了某些内容,但我们并未在Web应用程序中使用此功能。也许这是代理在Windows登录的客户网络中运行的方式? (我不是Windows专家。只是猜测。)

我没有关于基础设施的更多信息。

更新:2010年12月,可以通知一位管理员,包括:来自这里答案的链接。联系是因为代理引起的另一个问题。从那以后没有反馈。并且错误消息仍然存在。我笑着阻止我哭泣。

更新2:此问题自2008年中期以来一直存在。客户每隔几个月就会生气,并希望尽快修复。我们再次向他们发送所有旧电子邮件,并要求他们联系他们的管理员以修复它或进行一些进一步的测试。在2010年12月,我们能够向1位管理员发送一些信息。没有反馈。问题没有解决,我们不知道他们是否尝试过。 2011年5月,客户再次写信并希望修复此问题。自2008年以来掌握所有信息的人。

感谢所有答案。你帮助了很多人,正如我从这里的一些评论中看到的那样。太糟糕了现实世界对我来说是怪诞的。

更新3: 2012年5月,我想知道为什么我们没有收到另一个要求解决此问题(请参阅更新2)。查看错误协议,该协议仅在每次发生时报告此单个错误(大约每天15个)。它在2012年1月底停止了。没有人说什么。他们必须在网络上做点什么。现在一切都好。从2008年夏天到2012年1月。太糟糕了,我无法告诉你他们做了什么。

更新4: 2015年9月。网站必须收集一些数据并将其发送到客户的主网站。有一个帐户的API。每当出现问题时,他们都会联系我们,即使问题明显存在于另一方面。几周以来,我们无法向他们发送数据。该帐户不再可用。他们有重新启动,我找不到使用我们网站数据的页面了。错误报告没有回答,没有人投诉。我猜他们刚刚结束了这个项目。

更新5: 2017年3月.API在2015年夏天停止运作。客户似乎继续为该网站付费,并且仍在2017年2月访问它。我猜它们正在使用它作为档案。他们不再创建或更新任何数据,所以这个bug可能不会在2012年1月的神秘修复之后重新出现。但这可能是别人的问题。我要走了。

13 个答案:

答案 0 :(得分:40)

如果Internet Explorer从经过身份验证的站点(NTLM)发布到未经过身份验证的站点(匿名),则不会发送表单域。

这是challange-response情境(NTLM-或Kerberos-安全网站)的功能,IE可以预期第一个POST请求会立即导致 HTTP 401 Authentication Required 响应(包括挑战),实际上只接受第二个POST请求(包括对挑战的响应)。在这些情况下,由于性能原因,IE不会上传可能较大的请求正文和第一个请求。感谢EricLaw在评论中发布了一些信息。

每次从NTLM身份验证(即Intranet)页面到非身份验证(即Internet)页面进行HTTP POST时,或者如果未经身份验证的页面是框架集的一部分,则会发生此行为,其中框架集页面经过验证。

解决方法是使用GET请求作为表单方法,或者确保在新的选项卡/窗口(收藏夹/链接目标)中打开未经验证的页面,而不使用部分验证的框架集。只要整个窗口的身份验证模型一致,IE就会再次开始发送表单内容。


答案 1 :(得分:14)

使用MS-IE和服务器端的NTLM身份验证过滤器很容易重现。我在XP-SP2上遇到与JCIFS(1.2。),struts 1。和MS-IE 6/7相同的问题。它终于得到了修复。有几种解决方法可以弥补这一点。

  1. 将表单方法从POST(struts默认设置)更改为GET。 对于大多数小尺寸表单,它运行良好。不幸的是,我可能有超过50条记录要在HTTP流中发送回服务器端。 IE的GET URL限制为2038字节(不是参数长度,而是整个URL长度)。所以这是一个快速的解决方法,但不适用于我。

  2. 在执行POST操作之前发送GET。 这在MS-KB中被推荐。我的项目有许多遗留程序,我不会在合适的时间承担风险。我从来没有尝试过这个,因为根据我对MS-KB的理解,当过滤层收到GET时,它仍然需要一些额外的身份验证处理,我不想改变其他浏览器的行为,例如: Firefox,Opera。

  3. 检测POST是否以零内容长度发送(您可以从您的框架的头属性哈希结构中获取它)。 如果是这样,通过从DC或缓存获取质询代码来触发NTLM身份验证周期并期望NTLM响应。 当收到NTLM type2 msg并且会话仍然有效时,如果POST内容长度不为零,则不需要对用户进行身份验证,只需将其转发到预期的操作即可。顺便说一下,这会增加网络流量。因此,在应用更改plz之前,请检查缓存生命周期设置和SMB会话soTimeOut配置。 或者,更简单的说,您可能只是向MS-IE发送401未授权状态,浏览器将发回POST请求以及回复数据。

  4. MS-KB已经提供了KB-923155的热修复功能(由于声誉号码较低,我无法发布多个链接:{),但似乎无效。有人会在这里发布一个可行的热修复程序吗?谢谢:)这是一个供参考的链接http://www.websina.com/bugzero/kb/browser-ie.html

答案 2 :(得分:6)

我们系统上的客户遇到了完全相同的问题。我们已将其指向代理/防火墙。微软的IAS。它正在剥离POST主体并发送内容长度:0。然而,我们可以做很多事情,并且想要使用GET请求,因为这会在URL字符串上公开用户名/密码等。在我们的系统上有近7,000个用户,只有一个有问题...也只有一个使用Microsoft IAS,所以必须是这个。

答案 3 :(得分:4)

问题很可能是中间的代理服务器实现HTTP 1.0。

在HTTP 1.0中,您必须使用Content-Length标头字段:(See section 10.4 here

  

需要有效的Content-Length   所有HTTP / 1.0 POST请求。一个   HTTP / 1.0服务器应该响应   400(错误的请求)消息,如果它不能   确定请求的长度   消息的内容。

进入代理的请求是HTTP 1.1,因此不需要使用Content-Length头字段。通常使用Content-Length标头,但并非总是如此。请参阅HTTP 1.1 RFC S. 14.13的以下摘录。

  

应用程序应该使用此字段   表示转移的长度   消息体,除非是这样   被section 4.4中的规则所禁止。   任何Content-Length大于或   等于零是有效值。

     

4.4节描述了如何确定   消息体的长度,如果是   内容长度未给出。

因此代理服务器没有看到Content-Length标头,如果有正文,它在HTTP 1.0中绝对需要它。因此它假设为0,以便请求最终到达服务器。请记住,代理不知道HTTP 1.1规范的规则,因此当没有Content-Length头时它不知道如何处理这种情况。

您是否100%确定您的请求是否指定了Content-Length标头?如果它使用4.4节中定义的另一种方法,因为它认为服务器是1.1(因为它不知道中间的1.0代理),那么你将遇到你描述的问题。

也许您可以使用HTTP GET来绕过问题。

答案 4 :(得分:3)

这是Internet Explorer 6的一个已知问题,但不是我知道的7。您可以为IE6 KB831167修复程序安装此修复程序。

你可以read more about it here

有些问题:

  • 您知道哪种类型的代理?
  • 您是否知道请求中是否有实体发送?
  • 每次都会一直发生吗?或者只是有时候?
  • 请求中是否发送了二进制数据?也许数据以\ 0开头,而代理有二进制数据的错误。

答案 5 :(得分:2)

如果用户正在使用使用NTLM身份验证的ISA代理,那么听起来就像这个问题,它提供了一个解决方案(ISA代理的补丁)

http://support.microsoft.com/kb/942638
没有POST正文的POST请求可能会被发送到在ISA Server 2006中发布的Web服务器

答案 6 :(得分:1)

您确定这些请求来自“客户”吗?

我之前遇到过这个问题;他们有时会根据他们在抓取过程中发现的FORM标记中的操作URI发送空白POST请求来探测“联系我们”表单的网站。

答案 7 :(得分:1)

HTTP中的ContentLength标头的存在和可能的值在HTTP(我假设1/1)RFC中描述:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13

  

在HTTP中,只要在传输之前确定消息的长度,就应该发送

另见:

  

如果收到包含a的消息        Transfer-Encoding标头字段和Content-Length标头字段,        后者必须被忽略。   http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

也许你的邮件带有Transfer-Encoding标头?

稍后编辑:还请注意RFC中使用的“应该”是非常重要的,不等同于“必须”:

  

3。应该这个词,或形容词“推荐”,意思是那里      在特定情况下可能存在有效理由忽略a      特殊项目,但必须理解全部含义      在选择不同的课程之前仔细权衡。   参考:http://www.ietf.org/rfc/rfc2119.txt

答案 8 :(得分:0)

在https连接点击keepalive超时并重新连接到服务器后,Google也会将此信息显示为IE(某些版本,无论如何)错误。解决方案似乎是将服务器配置为不在https下使用keepalive for IE。

答案 9 :(得分:0)

Microsoft KB821814的修补程序可以将Content-Length设置为0:

  

本文介绍的修补程序将Wininet.dll中的代码更改实现为:

     
      
  • 检测POST请求中的RESET条件。
  •   
  • 保存要发布的数据。
  •   
  • 重试POST请求,并将内容长度设置为0.这可以防止重置发生,并允许完成身份验证过程。
  •   
  • 重试原始POST请求。
  •   

答案 10 :(得分:0)

我们让客户以匿名和NTLM模式(在不同的端口上)使用相同的网站。我们发现在我们的例子中,401与用于http优化的Riverbed Steelhead应用程序有关。指向我们的第一个信号是X-RBT-Optimized-By标头。问题是Gratuitous 401功能:

  

此功能可用于每个请求和每个连接   身份验证,但与每个请求一起使用时最有效   认证。对于每请求身份验证,每个请求必须是   在服务器提供服务之前对服务器进行身份验证   反对客户。但是,大多数浏览器都不缓存服务器   响应需要身份验证,因此会浪费一个   每次GET请求的往返。随着Gratuitous 401,客户端   Steelhead设备将缓存服务器响应和客户端时   发送GET请求时没有任何身份验证标头,它会   本地响应-401Unauthorized‖消息,因此保存   往返。请注意,HTTP模块不参与   实际认证本身。 HTTP模块的作用是通知   服务器要求身份验证而不需要的客户端   它浪费了一次往返。

答案 11 :(得分:0)

配置为使用HTTP代理时,

curl会向PUT/POST发送Content-Length: 0个请求。在第一次未经授权的PUT/POST代理请求的情况下克服所需缓冲的技巧。如果GET/HEAD请求curl只是重复查询。 PUT/POST的方案如下:

  1. PUT/POST设置为0的情况下发送第一个Content-Length请求。

  2. 得到答案。 HTTP状态代码为407表示我们必须使用代理 授权。为发送请求准备代理身份验证的标头。

  3. 再次发送请求,其中包含用于代理身份验证和实际数据的填充标头到POST / PUT。

答案 12 :(得分:0)

我还遇到一个问题,即来自客户IE 11浏览器的请求有Content-Length: 0且未包含预期的POST内容。当客户使用Firefox或Chrome时,预期内容已包含在请求中。

我找出原因是客户使用的是HTTP网址而不是HTTPS网址(例如http://...,而不是https://...),而我们的应用程序使用的是HSTS。 IE 11中似乎可能存在一个错误,当请求因HSTS而升级到HTTPS时,请求内容会丢失。

让客户更正https://...的网址,导致内容被包含在POST请求中并解决了问题。

我还没有在现阶段进一步调查它是否真的是IE 11中的一个错误。