2012-12-04 69 views
8

我在Linux服务器上运行Apache(2.2.14)上的PHP(PHP 5.3.2)应用程序。不止一次在其历史记录中,用户开始在其浏览器中看到以下消息:“请求实体太大”。 首先谷歌搜索建议,当上传的文件太大或Cookie太大时,会发生这种情况。但它不会发生在文件上传上,只有在登录时才会出现,并且始终在登录页面上。用户只需通过页面上的普通POST表单进入此页面。而cookies只包含会话ID。Apache,PHP无效的内容长度

此外,Apache正在记录“无效的内容长度”。这是在我的任何代码执行之前记录的。 $ _POST是空的,尽管它应该包含一些数据。当我加入以下行:

error_log("Content-Length: ".$_SERVER['CONTENT_LENGTH']); 

它说

Content-Length: 32, 32 

这似乎是确实无效。更改浏览器或重置用户PC似乎没有帮助。一切都在第二天才开始工作。

问题在哪里?是否有Apache,PHP,用户的网络设置?如果我需要添加更多信息,请告诉我。

+1

也许[这个答案](http://stackoverflow.com/questions/1361451/get-size-of-post-request-in-php#3259068)可能会有所帮助。 – Wh1T3h4Ck5

+0

我正在尝试其中一些选项,但没有结果。例如strlen(file_get_contents('php:// input'))为0. – PWojnar

+1

尝试:'strlen(file_get_contents('php:// stdin'))''而不是 – Dale

回答

2

调查此类问题的最简单方法是使用TCPDump将客户端和服务器之间发送的数据包捕获到文件中,然后使用Wireshark将数据包视为TCP流。

捕获数据包的命令的一个例子是。

的tcpdump -vvv -A -i eth0 '网络主机123.123.10.12 & &端口80' -w eth0.dat

因为它是你的登录页面,你可能需要的TCP流进行解码,因为它应该是后面HTTPS - 这可以通过指令来完成从http://segfault.in/2010/11/decrypt-https-traffic-using-wireshark-and-key-file/

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); 
      } 
     } 
    } 
} 
5

在过去的日子里,我们遇到了Apache在error_log中记录的“Invalid Content-Length”消息。 跟踪的问题,从只有几个特定的​​IP类的一些游客,例如阿根廷Movistar公司:200.81.44.201 进一步检查使用tcpdump/whireshark我们观察到POST请求中包含一些

duplicate Headers, namely Content-Length and Content-Type

真正的问题请求是的Content-Length,因为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_headers中使用,并SetEnvIfNoCase插在httpd.conf:

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 

您可以自由测试和使用此代码以过滤掉重复的Content-Length HTTP标头变量。