在使用xml-rpc的時候,server端擷取client資料,主要是通過php輸入資料流input,而不是$_POST數組。所以,這裡主要探討php輸入資料流php://input
對一php://input介紹,PHP官方手冊文檔有一段話對它進行了很明確地概述。
“php://input allows you to read raw POST data. It is a less memory intensive alternative to $HTTP_RAW_POST_DATA and does not need any special php.ini directives. php://input is not available with enctype=”multipart/form-data”.
翻譯過來,是這樣:
“php://input可以讀取沒有處理過的POST資料。相較於$HTTP_RAW_POST_DATA而言,它給記憶體帶來的壓力較小,並且不需要特殊的php.ini設定。php://input不能用於enctype=multipart/form-data”
我們應該怎麼去理解這段概述呢?!我把它劃分為三部分,逐步去理解。
1. 讀取POST資料
2. 不能用於multipart/form-data類型
3. php://input VS $HTTP_RAW_POST_DATA
讀取POST資料
PHPer們一定很熟悉$_POST這個內建變數。$_POST與php://input存在哪些關聯與區別呢?另外,用戶端向服務端互動資料,最常用的方法除了POST之外,還有GET。既然php://input作為PHP輸入資料流,它能讀取GET資料嗎?這二個問題正是我們這節需要探討的主要內容。
經驗告訴我們,從測試與觀察中總結,會是一個很湊效的方法。這裡,我寫了幾個指令碼來協助我們測試。
@file 192.168.0.6:/phpinput_server.php 列印出接收到的資料
@file 192.168.0.8:/phpinput_post.php 類比以POST方法提交表單資料
@file 192.168.0.8:/phpinput_xmlrpc.php 類比以POST方法發出xmlrpc請求.
@file 192.168.0.8:/phpinput_get.php 類比以GET方法提交表單表數
phpinput_server.php與phpinput_post.php
<?php
//@file phpinput_server.php
$raw_post_data = file_get_contents('php://input', 'r');
echo "-------\$_POST------------------\n";
echo var_dump($_POST) . "\n";
echo "-------php://input-------------\n";
echo $raw_post_data . "\n";
?>
<?php
//@file phpinput_post.php
$http_entity_body = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788');
$http_entity_type = 'application/x-www-form-urlencoded';
$http_entity_length = strlen($http_entity_body);
$host = '192.168.0.6';
$port = 80;
$path = '/phpinput_server.php';
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
fputs($fp, "POST {$path} HTTP/1.1\r\n");
fputs($fp, "Host: {$host}\r\n");
fputs($fp, "Content-Type: {$http_entity_type}\r\n");
fputs($fp, "Content-Length: {$http_entity_length}\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $http_entity_body . "\r\n\r\n");
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
fclose($fp);
echo $d;
}
?>
我們可以通過使用工具ngrep抓取http請求包(因為我們需要探知的是php://input,所以我們這裡只抓取http Request資料包)。我們來執行測試指令碼phpinput_post.php