当我从Java执行流上传到PHP时,我有时会收到PHP错误,指出输入变量超过了max_input_vars
的限制。
起初,我没有意识到原因。我先解释一下:
使用与此类似的方法上传文件:
// get file data from input stream
$putdata = fopen("php://input", "r");
$tmp = tmpfile();
filesize = stream_copy_to_stream ($putdata, $tmp);
fclose ($putdata);
// copy temp stream into destination stream
$target = fopen('myfile.dwg', "w");
fseek($tmp, 0, SEEK_SET);
stream_copy_to_stream($tmp, $target);
fclose($target);
fclose ($tmp);
为了了解为什么PHP会给我这样的警告,我收集了正在发送的数据:
file_put_contents ('input_vars.log', print_r ($_REQUEST, true));
file_put_contents ('php_input.log', file_get_contents ('php://input'));
这是有趣的部分: 上传的文件是1,8兆字节。生成的日志是:
input_vars.log
=> 5兆字节,90,000行php_input.log
=> 20兆字节,283,000行现在错误消息突然变得合法了。 php_input.log
只包含字节码,但input_vars.log
的格式如下:
Array
(
[filename] => 0018-101-001_67.dwg
[versionId] => 11253
[filetype] => dwg
[‘á‹Úê-8øFj–sÙ/ghÔ÷JJÐWhvPV] => ...
....
)
前三个键是通过GET发送的,其余的都是文件数据。如果我搜索并计算=>
的匹配项,我会得到25,954个匹配项。然后我假设REQUEST
拥有26,000个密钥。
现在,我的问题:
我已多次触发max_input_vars
值,现在它保持30000
的值。我应该忽略这个安全设置,并设置它尽可能高吗?
我担心的是,如果REQUEST数组大于30000
,它会从REQUEST数组中删除部分,从而使文件损坏。
将此值设置得太高会有任何安全问题吗?是否有更好的方法可以将文件上传到PHP?
答案 0 :(得分:2)
也许尝试将 enable_post_data_reading 指令设置为“false”(或“关闭”)以防止PHP解析文件正文?
顺便说一句,如果你使用的是PHP 5.3.9,你应该修补max_input_vars vulnerability。
答案 1 :(得分:2)
你想做什么,是PUT upload,你不应该把它作为POST来处理;或者 - 至少 - 将Content-Type
HTTP标头设置为application/octet-stream
答案 2 :(得分:1)
本身“php.net”(PHP.NET - max_input_vars),他们报告说你增加这个设置的值没有问题,但是,这是一种“使用这个指令减轻了可能性使用哈希冲突的拒绝服务攻击。“。
要解决此僵局,您可以尝试使用以下函数在运行时设置变量值:
ini_set("max_input_vars", 30000);
我最近遇到了这个问题以及调用是如何远程调用的,没有给出配置运行时,所以很遗憾我们不得不增加值。
到目前为止我们没有问题,但想法是未来,修改代码以按部件发送数据,从而将代码保持在标准当前配置的语言中。
答案 3 :(得分:0)
您没有展示如何使用Java上传文件。 PHP将普通的POST请求视为来自表单,并尝试从中解析字段 - 如果数据是二进制的,这是一个坏主意。您最好模仿HTML文件上传表单所做的事情并发送“多部分帖子”(example)。然后使用PHP's standard file upload handling functionality,就像从表单接收一样。
答案 4 :(得分:0)
接受的答案有效,但您必须注意,关闭enable_post_data_reading
也意味着关闭自动填充$_POST
,$_GET
和$_REQUEST
阵列。当我广泛使用这些数组时,我决定将enable_post_data_reading
限制为专用于文件上传的特定文件:
<Files "UploadFile.php">
php_value enable_post_data_reading Off
</Files>
因为我使用ajax请求上传,所以我可以这样设置用户定义的标题:
oXhr.setRequestHeader("X-File-Name", I_sFileName);
oXhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
通过这样做,您无需使用$_REQUEST
或$_POST
,因为您在php中获取信息:
$fileName = $_SERVER['HTTP_X_FILE_NAME'];
答案 5 :(得分:-1)
尝试在php.ini中增加post_max_size,upload_max_filesize和max_file_uploads的大小