Apache、PHP无效的内容长度
我在Linux服务器上的Apache(2.2.14)上运行了一个PHP(PHP5.3.2)应用程序。在其历史记录中,用户再次开始在浏览器中看到以下消息:“请求实体太大”。 第一次谷歌搜索表明,当上传的文件太大或cookie太大时,就会发生这种情况。但这并不是发生在文件上传上,只是在登录时,总是在登录页面上。用户仅通过页面上的普通POST表单进入此页面。Cookie仅包含会话id 此外,apache正在记录“无效内容长度”。这是在我的任何代码执行之前记录的$_POST为空,尽管它应该包含一些数据。当我添加以下行时:Apache、PHP无效的内容长度,php,apache,Php,Apache,我在Linux服务器上的Apache(2.2.14)上运行了一个PHP(PHP5.3.2)应用程序。在其历史记录中,用户再次开始在浏览器中看到以下消息:“请求实体太大”。 第一次谷歌搜索表明,当上传的文件太大或cookie太大时,就会发生这种情况。但这并不是发生在文件上传上,只是在登录时,总是在登录页面上。用户仅通过页面上的普通POST表单进入此页面。Cookie仅包含会话id 此外,apache正在记录“无效内容长度”。这是在我的任何代码执行之前记录的$_POST为空,尽管它应该包含一些数据。
error_log("Content-Length: ".$_SERVER['CONTENT_LENGTH']);
上面说
Content-Length: 32, 32
这似乎确实是无效的。更改浏览器或重置用户PC似乎没有帮助。第二天一切都开始工作了
问题出在哪里?它与Apache、PHP、用户的网络设置有关吗?如果需要添加更多信息,请告诉我。调查此类问题的最简单方法是使用捕获客户端和服务器之间发送到文件的数据包,然后使用将数据包作为TCP流查看 捕获数据包的命令示例如下 tcpdump-vvv-A-i eth0'主机123.123.10.12和端口80'-w eth0.dat 由于这是您的登录页面,您可能需要解码TCP流,因为它应该位于HTTPS后面-这可以使用 不过,Plasmid87几乎可以肯定是正确的——它听起来像是其中一个头文件正在大量增长,并最终变得比Apache LimitRequestFieldSize更大 只要它增长缓慢,而不是一下子全部增长,你就可以通过检查全局变量来研究它
function checkVars(){
$varsToCheck = array($GLOBALS, $_SERVER, $_GET, $_POST, $_FILES, $_REQUEST, $_SESSION, $_ENV, $_COOKIE);
foreach($varToCheck as $var){
foreach($var as $key => $value){
if(count($key) > 1024){
logToFile("Found ridiculous key: ".$key." value is ".$value);
}
if(count($value) > 1024){
logToFile("Found ridiculous value for key: ".$key." value is ".$value);
}
}
}
}
在过去的几天中,我们遇到Apache在错误日志中记录的“无效内容长度”消息。 跟踪了一些特定IP类别的访问者的问题,例如Movistar Argentina:200.81.44.201 通过tcpdump/whireshark进一步检查请求,我们发现POST请求包含一些 重复的标题,即内容长度和内容类型 真正的问题在于内容长度,因为Apache通过连接多个变量来处理多个变量,例如:
Content-Length: 51
Content-Length: 51
结果将是:
Content-Length: 51, 51
然后Apache尝试将字符串“51,51”转换为一个不可能的整数。
在较新的Apache>2.2.17中,或者使用后端口补丁时,Apache会记录一个错误:413请求实体太大,而在较旧的Apache中,该过程只会占用大量CPU时间。
在这个IP类的背后,我们看到了更多不同的客户端,所以它们可能是错误配置的3G网关代理服务器,因为它们复制了那个报头。
因此,我们找到了一个解决方案,将Apache配置为只使用一个内容长度和一个内容类型头重写请求:
下面是我的代码,使用mod_头和httpd.conf中插入的SetEnvIfNoCase:
SetEnvIfNoCase Content-Length (.*), MyContentLength=$1
SetEnvIfNoCase Content-Type (.*), MyContentType=$1
RequestHeader set Content-Length: "%{MyContentLength}e" env=MyContentLength
RequestHeader set Content-Type: "%{MyContentType}e" env=MyContentType
您可以自由测试和使用此代码,以筛选出重复的内容长度HTTP头变量。可能会有所帮助。我尝试了其中一些选项,但没有结果。例如strlen(文件获取内容('php://input“))是0。请尝试:
strlen(文件获取内容(”)php://stdin)
相反,谢谢,我会尝试一下,但问题是我无法重现这个问题,它只是偶尔发生。现在,在成功登录期间,php://input 给出了立柱和立柱的实际长度php://stdin 给0。除此之外,我不需要获取POST长度,我需要找出apache(有时)导致此错误的原因,以及为什么我无法在POST中获取任何数据。请仔细检查服务器上的$\u COOKIE值,我建议var\u dump($\u COOKIE)代码>在正常工作条件下。如果在随后的请求之后,这一长度似乎在增长,这很可能就是问题所在。我以前遇到过这样的问题,每次后续请求后,cookie的大小都会以指数级的速度增加。您是否碰巧尝试过3+个重复的头?它对两个人有效,但不会更多。IIS似乎并不关心并接受给定数量的内容长度头,
function checkVars(){
$varsToCheck = array($GLOBALS, $_SERVER, $_GET, $_POST, $_FILES, $_REQUEST, $_SESSION, $_ENV, $_COOKIE);
foreach($varToCheck as $var){
foreach($var as $key => $value){
if(count($key) > 1024){
logToFile("Found ridiculous key: ".$key." value is ".$value);
}
if(count($value) > 1024){
logToFile("Found ridiculous value for key: ".$key." value is ".$value);
}
}
}
}