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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/328281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 05:47:47  来源:igfitidea点击:

Why "Content-Length: 0" in POST requests?

windowsinternet-explorerhttpweb-applicationsproxy

提问by stesch

A customer sometimes sends POST requests with Content-Length: 0when submitting a form (10 to over 40 fields).

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

We tested it with different browsers and from different locations but couldn't reproduce the error. The customer is using Internet Explorer 7 and a proxy.

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

We asked them to let their system administrator see into the problem from their side. Running some tests without the proxy, etc..

我们要求他们让他们的系统管理员从他们的角度查看问题。在没有代理的情况下运行一些测试等。

In the meantime (half a year later and still no answer) I'm curious if somebody else knows of similar problems with a Content-Length: 0request. Maybe from inside some Windows network with a special proxy for big companies.

与此同时(半年后仍然没有答案)我很好奇是否有人知道Content-Length: 0请求有类似的问题。也许来自一些 Windows 网络内部,为大公司提供特殊代理。

Is there a known problem with Internet Explorer 7? With a proxy system? The Windows network itself?

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

Google only showed something in the context of NTLM (and such) authentication, but we aren't using this in the web application. Maybe it's in the way the proxy operates in the customer's network with Windows logins? (I'm no Windows expert. Just guessing.)

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

I have no further information about the infrastructure.

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

UPDATE:In December 2010 it was possible to inform one administrator about this, incl. links from the answers here. Contact was because of another problem which was caused by the proxy, too. No feedback since then. And the error messages are still there. I'm laughing to prevent me from crying.

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

UPDATE 2:This problem exists since mid 2008. Every few months the customer is annoyed and wants it to be fixed ASAP. We send them all the old e-mails again and ask them to contact their administrators to either fix it or run some further tests. In December 2010 we were able to send some information to 1 administrator. No feedback. Problem isn't fixed and we don't know if they even tried. And in May 2011 the customer writes again and wants this to be fixed. The same person who has all the information since 2008.

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

Thanks for all the answers. You helped a lot of people, as I can see from some comments here. Too bad the real world is this grotesque for me.

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

UPDATE 3:May 2012 and I was wondering why we hadn't received another demand to fix this (see UPDATE 2). Looked into the error protocol, which only reports this single error every time it happened (about 15 a day). It stopped end of January 2012. Nobody said anything. They must have done something with their network. Everything is OK now. From summer 2008 to January 2012. Too bad I can't tell you what they have done.

更新 3:2012 年 5 月,我想知道为什么我们没有收到另一个修复此问题的要求(请参阅更新 2)。查看错误协议,它每次发生时只报告这个错误(大约每天 15 个)。它在 2012 年 1 月结束。没有人说什么。他们一定对他们的网络做了什么。现在一切正常。从 2008 年夏天到 2012 年 1 月。太糟糕了,我不能告诉你他们做了什么。

UPDATE 4:September 2015. The website had to collect some data and deliver it to the main website of the customer. There was an API with an account. Whenever there was a problem they contacted us, even if the problem was clearly on the other side. For a few weeks now we can't send them the data. The account isn't available anymore. They had a relaunch and I can't find the pages anymore that used the data of our site. The bug report isn't answered and nobody complaint. I guess they just ended this project.

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

UPDATE 5:March 2017. The API stopped working in the summer of 2015. The customer seems to continue paying for the site and is still accessing it in February 2017. I'm guessing they use it as an archive. They don't create or update any data anymore so this bug probably won't reemerge after the mysterious fix of January 2012. But this would be someone else's problem. I'm leaving.

更新 5:2017 年 3 月。API 在 2015 年夏天停止工作。客户似乎继续为该网站付费,并且仍在 2017 年 2 月访问它。我猜他们将其用作存档。他们不再创建或更新任何数据,因此在 2012 年 1 月的神秘修复之后,此错误可能不会再次出现。但这将是其他人的问题。我走了。

回答by Tomalak

Internet Explorer does not send form fields if they are posted from an authenticated site (NTLM) to a non-authenticated site (anonymous).

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

This is feature for challange-response situations (NTLM- or Kerberos- secured web sites) where IE can expect that the first POST request immediately leads to an HTTP 401 Authentication Requiredresponse (which includes a challenge), and only the second POST request (which includes the response to the challange) will actually be accepted. In these situations IE does not upload the possibly large request body with the first request for performance reasons. Thanks to EricLawfor posting that bit of information in the comments.

这是针对挑战响应情况(NTLM 或 Kerberos 保护的网站)的功能,其中 IE 可以预期第一个 POST 请求会立即导致HTTP 401 需要身份验证的响应(包括挑战),并且只有第二个 POST 请求(其中包括对挑战的回应)实际上将被接受。在这些情况下,出于性能原因,IE 不会在第一个请求中上传可能很大的请求正文。感谢EricLaw在评论中发布了这些信息。

This behavior occurs every time an HTTP POST is made from a NTLM authenticated (i.e. Intranet) page to a non-authenticated (i.e. Internet) page, or if the non-authenticated page is part of a frameset, where the frameset page is authenticated.

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

The work-around is either to use a GET request as the form method, or to make sure the non-authenticated page is opened in a fresh tab/window (favorite/link target) without a partly authenticated frameset. As soon as the authentication model for the whole window is consistent, IE will start to send form contents again.

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



回答by maxwu

This is easy to reproduce with MS-IE and an NTLM authentication filter on server side. I have the same issue with JCIFS (1.2.), struts 1.and MS-IE 6/7 on XP-SP2. It was finally fixed. There are several workarounds to make it up.

这很容易通过 MS-IE 和服务器端的 NTLM 身份验证过滤器重现。我对 XP-SP2 上的JCIFS (1.2. )、struts 1.和 MS-IE 6/7有同样的问题。终于修好了。有几种解决方法可以弥补。

  1. change form method from POST (struts default setting) to GET. For most pages with small sized forms, it works well. Unfortunately i have possibly more than 50 records to send in HTTP stream back to server side. IE has a GET URL limit 2038 Bytes (not parameter length, but the whole URL length). So this is a quick workaround but not applicable for me.

  2. send a GET before POST action executing. This was recommended in MS-KB. My project has many legacy procedures and i would not take the risk at the right time. I have never tried this because it still needs some extra authentication processing when GET is received by filter layer based on my understanding from MS-KB and I would not like to change the behavior with other browsers, e.g. Firefox, Opera.

  3. detecting if POST was sent with zero content-length (you may get it from header properties hash structure with your framework). If so, trigger an NTLM authentication cycle by get challenge code from DC or cache and expect an NTLM response. When the NTLM type2 msg is received and the session is still valid, you don't really need to authenticate the user but just forward it to the expected action if POST content-length is not zero. BTW, this would increase the network traffics. So check your cache life time setting and SMB session soTimeOut configuration before applying the change plz. Or, more simple, you may just send a 401-unauthorized status to MS-IE and the browser shall send back POST request with data in reply.

  4. MS-KB has provided a hot-fix with KB-923155 (I could not post more than one link because of a low reputation number :{ ) , but it seems not working. Would someone post a workable hot-fix here? Thanks :) Here is a link for reference, http://www.websina.com/bugzero/kb/browser-ie.html

  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 content-length 不为零,您实际上不需要对用户进行身份验证,而只需将其转发到预期的操作。顺便说一句,这会增加网络流量。因此,请在应用更改之前检查您的缓存生存时间设置和 SMB 会话 soTimeOut 配置。或者,更简单的是,您可以向 MS-IE 发送 401-unauthorized 状态,浏览器将发送回带有数据的 POST 请求作为回复。

  4. MS-KB 提供了 KB-923155 的修补程序(由于信誉号低,我不能发布多个链接 :{ ),但它似乎不起作用。有人会在这里发布可行的修补程序吗?谢谢:) 这是一个参考链接,http://www.websina.com/bugzero/kb/browser-ie.html

回答by maxwu

We have a customer on our system with exactly the same problem. We've pin pointed it down to the proxy/firewall. Microsoft's IAS. It's stripping the POST body and sending content-length: 0. Not a lot we can do to work around however, and down want to use GET requests as this exposes usernames/passwords etc on the URL string. There's nearly 7,000 users on our system and only one with the problem... also only one using Microsoft IAS, so it has to be this.

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

回答by Brian R. Bondy

There's a good chance the problem is that the proxy server in between implements HTTP 1.0.

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

In HTTP 1.0 you must use the Content-Length header field: (See section 10.4 here)

在 HTTP 1.0 中,您必须使用 Content-Length 标头字段:(请参阅此处的第 10.4 节

A valid Content-Length is required on all HTTP/1.0 POST requests. An HTTP/1.0 server should respond with a 400 (bad request) message if it cannot determine the length of the request message's content.

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

The request going into the proxy is HTTP 1.1 and therefore does not need to use the Content-Length header field. The Content-Length header is usually used but not always. See the following excerpt from the HTTP 1.1 RFC S. 14.13.

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

Applications SHOULD use this field to indicate the transfer-length of the message-body, unless this is prohibited by the rules in section 4.4. Any Content-Length greater than or equal to zero is a valid value.

Section 4.4describes how to determine the length of a message-body if a Content-Length is not given.

应用程序应该使用这个字段来指示消息体的传输长度,除非4.4 节中的规则禁止这样做。任何大于或等于零的 Content-Length 都是有效值。

4.4节描述了如果没有给出 Content-Length,如何确定消息体的长度。

So the proxy server does not see the Content-Length header, which it assumes is absolutely needed in HTTP 1.0 if there is a body. So it assumes 0 so that the request will eventually reach the server. Remember the proxy doesn't know the rules of the HTTP 1.1 spec, so it doesn't know how to handle the situation when there is no Content-Length header.

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

Are you 100% sure your request is specifying the Content-Length header? If it is using another means as defined in section 4.4 because it thinks the server is 1.1 (because it doesn't know about the 1.0 proxy in between) then you will have your described problem.

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

Perhaps you can use HTTP GET instead to bypass the problem.

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

回答by Brian R. Bondy

This is a known problem for Internet explorer 6, but not for 7 that I know of. You can install this fix for the IE6 KB831167fix.

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

You can read more about it here.

您可以在此处阅读更多相关信息

Some questions for you:

一些问题给你:

  • Do you know which type of proxy?
  • Do you know if there is an actual body sent in the request?
  • Does it happen consistently every time? Or only sometimes?
  • Is there any binary data sent in the request? Maybe the data starts with a \0 and the proxy has a bug with binary data.
  • 你知道什么类型的代理吗?
  • 您知道请求中是否发送了实际的正文吗?
  • 是否每次都持续发生?还是只是偶尔?
  • 请求中是否发送了任何二进制数据?也许数据以 \0 开头,并且代理有二进制数据的错误。

回答by GStephens

If the user is going through an ISA proxy that uses NTLM authentication, then it sounds like this issue, which has a solution provided (a patch to the ISA proxy)

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

http://support.microsoft.com/kb/942638
POST requests that do not have a POST body may be sent to a Web server that is published in ISA Server 2006

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

回答by matthewrwilton

I also had a problem where requests from a customer's IE 11 browser had Content-Length: 0and did not include the expected POST content. When the customer used Firefox, or Chrome the expected content was included in the request.

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

I worked out the cause was the customer was using a HTTP URL instead of a HTTPS URL (e.g. http://..., not https://...) and our application uses HSTS. It seems there might be a bug in IE 11 that when a request gets upgraded to HTTPS due to HSTS the request content gets lost.

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

Getting the customer to correct the URL to https://...resulted in the content being included in the POST request and resolved the problem.

让客户更正 URL 以https://...导致内容包含在 POST 请求中并解决了问题。

I haven't investigated whether it is actually a bug in IE 11 any further at this stage.

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

回答by JasonTrue

Are you sure these requests are coming from a "customer"?

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

I've had this issue with bots before; they sometimes probe sites for "contact us" forms by sending blank POST requests based on the action URI in FORM tags they discover during crawling.

我以前在机器人上遇到过这个问题;他们有时会根据他们在爬行过程中发现的 FORM 标签中的操作 URI 发送空白 POST 请求来探测“联系我们”表单的站点。

回答by diciu

Presence and possible values of the ContentLength header in HTTP are described in the HTTP ( I assume 1/1) RFC:

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

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

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

In HTTP, it SHOULD be sent whenever the message's length can be determined prior to being transferred

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

See also:

也可以看看:

If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

如果接收到的消息同时带有 Transfer-Encoding 头域和 Content-Length 头域,后者必须被忽略。http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

Maybe your message is carrying a Transfer-Encoding header?

也许您的消息带有 Transfer-Encoding 标头?

Later edit: also please note "SHOULD" as used in the RFC is very important and not equivalent to "MUST":

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

3. SHOULD This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course.Ref: http://www.ietf.org/rfc/rfc2119.txt

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

回答by diciu

Microsoft's hotfix for KB821814can set Content-Length to 0:

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

The hotfix that this article describes implements a code change in Wininet.dll to:

  • Detect the RESET condition on a POST request.
  • Save the data that is to be posted.
  • Retry the POST request with the content length set to 0. This prevents the reset from occurring and permits the authentication process to complete.
  • Retry the original POST request.

本文描述的修补程序在 Wininet.dll 中实现了代码更改:

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