1. 程式人生 > >PHP輸入流php://input介紹

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” 


我們應該怎麼去理解這段概述呢?!我把它劃分為三部分,逐步去理解。 
讀取POST資料 
不能用於multipart/form-data型別 
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 

@php /phpinput_post.php 
HTTP/1.1 200 OK 
Date: Thu, 08 Apr 2010 03:23:36 GMT 
Server: Apache/2.2.3 (CentOS) 
X-Powered-By: PHP/5.1.6 
Content-Length: 160 
Connection: close 
Content-Type: text/html; charset=UTF-8 
-------$_POST------------------ 
array(2) { 
["n"]=> string(9) "perfgeeks" 
["p"]=> string(4) "7788" 

-------php://input------------- 
n=perfgeeks&p=7788 
通過ngrep抓到的http請求包如下: 

T 192.168.0.8:57846 -> 192.168.0.6:80 [AP] 
POST /phpinput_server.php HTTP/1.1.. 
Host: 192.168.0.6..Content-Type: application/x-www-form-urlencoded..Co 
ntent-Length: 18..Connection: close....n=perfgeeks&p=7788.... 
仔細觀察,我們不難發現 
1,$_POST資料,php://input 資料與httpd entity body資料是“一致”的 
2,http請求中的Content-Type是application/x-www-form-urlencoded ,它表示http請求body中的資料是使用http的post方法提交的表單資料,並且進行了urlencode()處理。 
(注:注意加粗部分內容,下文不再提示). 

我們再來看看指令碼phpinput_xmlrpc.php的原檔案內容,它模擬了一個POST方法提交的xml-rpc請求。 



<?php 
//@file phpinput_xmlrpc.php 
$http_entity_body = "\n\n jt_userinfo\n"; 
$http_entity_type = 'text/html'; 
$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; 

?> 
同樣地,讓我們來執行這個測試指令碼 

@php /phpinput_xmlrcp.php 
HTTP/1.1 200 OK 
Date: Thu, 08 Apr 2010 03:47:18 GMT 
Server: Apache/2.2.3 (CentOS) 
X-Powered-By: PHP/5.1.6 
Content-Length: 154 
Connection: close 
Content-Type: text/html; charset=UTF-8 

-------$_POST------------------ 
array(0) { 


-------php://input------------- 
<?xml version="1.0"> 
<methodcall> 
<name>jt_userinfo</name> 
</methodcall> 
執行這個指令碼的時候,我們通過ngrep抓取的http請求資料包如下 

T 192.168.0.8:45570 -> 192.168.0.6:80 [AP] 
POST /phpinput_server.php HTTP/1.1.. 
Host: 192.168.0.6..Content-Type: text/html..Content-Length: 75..Connec 
tion: close....<?xml version="1.0">.<methodcall>. <name>jt_userinfo< 
/name>.</methodcall>.... 
同樣,我樣也可以很容易地發現: 
1,http請求中的Content-Type是text/xml。它表示http請求中的body資料是xml資料格式。 
2,服務端$_POST打印出來的是一個空陣列,即與http entity body不一致了。這跟上個例子不一樣了,這裡的Content-Type是text/xml,而不是application/x-www-form-urlencoded 
3,而php://input資料還是跟http entity body資料一致。也就是php://input資料和$_POST資料不一致了。 

我們再來看看通過GET方法提交表單資料的情況,php://input能不能讀取到GET方法的表單資料?在這裡,我們稍加改動一下phpinput_server.php檔案,將$_POST改成$_GET。 

複製程式碼程式碼如下:
<?php 
//@file phpinput_server.php 
$raw_post_data = file_get_contents('php://input', 'r'); 
echo "-------\$_GET------------------\n"; 
echo var_dump($_GET) . "\n"; 
echo "-------php://input-------------\n"; 
echo $raw_post_data . "\n"; 
?> 
<?php 
//@file phpinput_get.php 
$query_path = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788'); 
$host = '192.168.0.6'; 
$port = 80; 
$path = '/phpinput_server.php'; 
$d = ''; 
$fp = fsockopen($host, $port, $error_no, $error_desc, 30); 
if ($fp) { 
fputs($fp, "GET {$path}?{$query_path} HTTP/1.1\r\n"); 
fputs($fp, "Host: {$host}\r\n"); 
fputs($fp, "Connection: close\r\n\r\n"); 

while (!feof($fp)) { 
$d .= fgets($fp, 4096); 

fclose($fp); 
echo $d; 

?> 

同樣,我們執行下一phpinput_get.php測試指令碼,它模擬了一個通常情況下的GET方法提交表單資料。

@php /phpinput_get.php 
HTTP/1.1 200 OK 
Date: Thu, 08 Apr 2010 07:38:15 GMT 
Server: Apache/2.2.3 (CentOS) 
X-Powered-By: PHP/5.1.6 
Content-Length: 141 
Connection: close 
Content-Type: text/html; charset=UTF-8 

-------$_GET------------------ 
array(2) { 
["n"]=> 
string(9) "perfgeeks" 
["p"]=> 
string(4) "7788" 


-------php://input------------- 
在這個時候,使用ngrep工具,捕獲的相應的http請求資料包如下 

T 192.168.0.8:36775 -> 192.168.0.6:80 [AP] 
GET /phpinput_server.php?n=perfgeeks&p=7788 HTTP/1.1.. 
Host: 192.168.0.6..Connection: close.... 
比較POST方法提交的http請求,通常GET方法提交的請求中,entity body為空。同時,不會指定Content-Type和Content-Length。但是,如果強硬資料http entity body,並指明正確地Content-Type和Content-Length,那麼php://input還可是讀取得到http entity body資料,但不是$_GET資料。 

所根據,上面幾個探測,我們可以作出以下總結: 
1,Content- Type取值為application/x-www-form-urlencoded時,php會將http請求body相應資料會填入到數 組$_POST,填入到$_POST陣列中的資料是進行urldecode()解析的結果。(其實,除了該Content-Type,還有 multipart/form-data表示資料是表單資料,稍後我們介紹) 
2,php://input資料,只要Content-Type不為 multipart/form-data(該條件限制稍後會介紹)。那麼php://input資料與http entity body部分資料是一致的。該部分相一致的資料的長度由Content-Length指定。 
3,僅當Content-Type為application/x-www-form-urlencoded且提交方法是POST方法時,$_POST資料與php://input資料才是”一致”(打上引號,表示它們格式不一致,內容一致)的。其它情況,它們都不一致。 
4,php://input讀取不到$_GET資料。是因為$_GET資料作為query_path寫在http請求頭部(header)的PATH欄位,而不是寫在http請求的body部分。 

這也幫助我們理解了,為什麼xml_rpc服務端讀取資料都是通過file_get_contents(‘php://input', ‘r')。而不是從$_POST中讀取,正是因為xml_rpc資料規格是xml,它的Content-Type是text/xml。 
php://input碰到了multipart/form-data 

上傳檔案的時候,表單的寫法是這樣的 

複製程式碼程式碼如下:
<form enctype="multipart/form-data" action="phpinput_server.php" method="POST" > 
<input type="text" name="n" /> 
<input type="file" name="f" /> 
<input type="submit" value="upload now" /> 
</form> 

那麼,enctype=multipart/form-data這裡的意義,就是將該次http請求頭部(head)中的Content-Type設定為multipart/form-data。請查閱RFC1867對 它的描述。multipart/form-data也表示以POST方法提交表單資料,它還伴隨了檔案上傳,所以會跟application/x- www-form-urlencoded資料格式不一樣。它會以一更種更合理的,更高效的資料格式傳遞給服務端。我們提交該表單資料,並且打印出響應結 果,如下: 

-------$_POST------------------ 
array(1) { ["n"]=> string(9) "perfgeeks" } 
-------php://input------------- 
同時,我們通過ngrep抓取的相應的http請求資料包如下: 

######## 
T 192.168.0.8:3981 -> 192.168.0.6:80 [AP] 
POST /phpinput_server.php HTTP/1.1..Host: 192.168.0.6..Connection: kee 

相關推薦

PHP輸入php://input介紹

對一php://input介紹,PHP官方手冊文件有一段話對它進行了很明確地概述。 “php://input allows you to read raw POST data. It is a less memory intensive alternative to $HT

深入剖析PHP輸入 php://input

$data = file_get_contents("php://input"); php://input 是個可以訪問請求的原始資料的只讀流。 POST 請求的情況下,最好使用 php://input 來代替 $HTTP_RAW_POST_DATA,因為它不依賴於特定的 php.ini 指令。

PHP輸入 php://input 相關【轉】

為什麼xml_rpc服務端讀取資料都是通過file_get_contents(‘php://input', ‘r')。而不是從$_POST中讀取,正是因為xml_rpc資料規格是xml,它的Content-Type是text/xml。php://input碰到了multipart/form-data在使用xm

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 an

PHP輸入php://input

在使用xml-rpc的時候,server端獲取client資料,主要是通過php輸入流input,而不是$_POST陣列。所以,這裡主要探討php輸入流php://input    對一php://input介紹,PHP官方手冊文件有一段話對它進行了很明確地概述。    “php://input allows

php輸入php://input使用淺析

在做一個攝像頭拍照然後上傳的功能,php中使用php://input來獲取內容。於是就瞭解了下php://input。 從官網資訊來看,php://input是一個只讀資訊流,當請求方式是post的,並且enctype不等於”multipart/form-data”時,可以

有關PHP表單中 input type型別的介紹

1、在學習PHP過程中,會經常遇到建立各種各樣的表單,比如說以上傳一個檔案為例子: 注意:在<form>標記中,必須設定屬性enctype=“multipart/form-data”,這樣伺服器可以知道上傳檔案帶有的常規的表單資訊 必須有一個可以設定上傳檔案最

PHP 輸入輸出合集

開發十年,就只剩下這套架構體系了! >>>   

PHP - 輸入字段

PHP - 輸入字段 從上一節中的驗證規則中,我們看到 "Name", "E-mail" 以及 "Gender" 字段是必需的。這些字段不能為空且必須在 HTML 表單中填寫。 字段 驗證規則 Name 必需。必須包含字母和空格。 E-mail 必需。必須包含有效的電子郵件地址(包含 @ 和 .)。

12.1 LNMP架構介紹 12.2 MySQL安裝 12.3/12.4 PHP安裝 12.5 Nginx介紹

mcrypt .... game post mcr default .tar.gz sta fig Nginx設計的初衷是提供一種快速、高效、多並發的Web服務軟件。在靜態頁面的處理上,Nginx較Apache更勝一籌;但是在動態頁面的處理上,Nginx並不比Apache

LNMP架構結介紹,MySQL和PHP的安裝以及Nginx介紹

LNMP php-fpm Nginx 一、LNMP架構結介紹 LNMP代表的就是:Linux系統下Nginx+MySQL+PHP這種網站服務器架構。Nginx中的PHP是以fastcgi的方式結合Nginx的,可以理解為Nginx代理了PHP的fastcgi。 詳細介紹可參考:http://b

php協議

除了 解析器 NPU following 源代碼 目錄文件 test 特性 針對 文件包含漏洞結合php協議流的特性,使得漏洞利用效率更高,下面的內容主要講解協議流的使用。 0x00 測試環境: 具體為5.2,5.3,5.5,7.0 0x01 測試代碼: &

redis的資料型別List,其原生命令和php操作Redis List函式介紹

List型別介紹 List是簡單的字串列表,按照插入順序排序,可以從列表的兩頭新增資料,一個列表最多可以包含2^32-1個元素(超過40億個元素) List原生命令 命令 命令描述 例項 LPUSH key value1 [va

PHP工作

利用本篇文章整理記錄一下我的PHP工作流,本篇文章只代表了我目前的對php開發工作流的理解,本文會隨時更新 IDE PhpStorm 不解釋,反正無論你用什麼,最後還是會回到這個上面,我就是不信邪,折騰了一圈,還是乖乖的用了它. 包管理 composer PHP檢查 PH

PHP 輸入多個經緯度座標 找出中心點

參考: https://stackoverflow.com/questions/6671183/calculate-the-center-point-of-multiple-latitude-longitude-coordinate-pairs Python Java C# Ja

PHP PSR 程式碼規範基本介紹

PSR 是 PHP Standard Recommendation 的簡寫,即PHP推薦標準。 目前通過的規範有 PSR-0(Autoloading Standard)、PSR-1(Basic Coding Standard)、PSR-2(Coding Style Guide)、PSR-3(Logger I

PHP】關於php://input、$_POST、$HTTP_RAW_POST_DATA的理解及區別

首先明確一點,json格式的資料指的的http頭body的字串是一個json格式的字串。這個在PHP中無法通過$_POST取到,php底層沒有對這種方式進行處理。 手冊中有關php://input的說明 當 HTTP POST 請求的 Content-T

PHP之PSR2編碼指南介紹(一)

本指南擴充套件和擴充套件了基本編碼標準PSR-1。 本指南的目的是在掃描來自不同作者的程式碼時減少認知摩擦。它通過列舉一組共享規則和對如何格式化PHP程式碼的期望來實現。 這裡的風格規則源於各個成員專案之間的共性。當各個作者跨多個專案進行協作時,在所有這些專案中使用一套指南會

redis的資料型別Set,其原生命令和php操作Redis Set函式介紹

sRandMember(key,[count])函式 * 說明:從集合key中隨機取出一個或count個成員,但是不移除key中的成員 * 引數:key(集合的名稱),count(可選項,隨機取出成員的個數) * 返回值:沒有count引數,返回key中的一個成員(string);存在count,則返回隨機取

CI框架去掉index.php以及解決No input file specified問題

以下問題都容易解決,在此簡述 1,開啟apache的httpd.conf,開啟rewrite_module,並且將AllowOverride None改為AllowOverride None。 2,在專案中,和index.php以及system資料夾同級的目錄中,新建.htaccess檔