搜尋
首頁php教程PHP开发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 diultives. php:// /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之外,還有GET。探討的主要內容。 php 列印收到的資料 
@file 192.168.0.8:/phpinput_post.php 模擬以POST方法提交表單資料 
@file 192.168.0.8:/phpinput_xmlrpc.php 模擬以使用POST方法發出xmlc85. :/phpinput_get.php 模擬以GET方法提交表單表數 
phpinput_server.php與phpinput_post.php 



//@file phpinput_server.. 'r'); 
echo "-------$_POST------------------n"; 
echo var_dump($_POST) . "n";
echo "-------php://input-------------n"; 
echo $raw_post_data . "n"; 
?> 

/ /@file phpinput_post.php 
$http_entity_body = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788'); 
$http_entity_type = 'application/mwww-form-url;
$http_entity_length = strlen($http_entity_body); 
$host = '192.168.0.6'; 
$port = 80; 
$path = '/phpinput_server.com';$port = 80; 
$path = '/phpinput_server..;$port = 80; 
$path = '/phpinput_server..;$port = 80; 
$path = '/phpinput_server..'; error_no, $error_desc, 30); 
if ($fp) { 
fputs($fp, "POST {$path} HTTP/1.1.1rn"); 
fputs($fp, "Host: {$host}rn"); 
fputs($fp, "Host: {$host}rn") ; 
fputs($fp, "Content-Type: {$http_entity_type}rn"); 
fputs($fp, "Content-Length: {$http_entity_length}rn"); 
fputs($ffp, ": cernwernConnection" ); 
fputs($fp, $http_entity_body . "rnrn"); 

while (!feof($fp)) { 
$d .= fgets($fp, 4096); 
$d .= fgets($fp, 4096); 
$d .= fgets($fp, 4096); 
}
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 . 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..Contength 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請求。 



//@file phpinput_xmlrpc.php 
$http_entity_body = "nn jt_userinfon"; 
$http_entity_type = 'text/html'; 
$http_entity_length = strlen($http_entity_body); 
f = '192.168.0.6'? phpinput_server.php'; 
$fp = fsockopen($host, $port, $error_no, $error_desc, 30); 
if ($fp) { 
fputs($fp, "POST {$path= HTTP/1.1" ); 
fputs($fp, "主機: {$host}rn"); 
fputs($fp, "內容類型: {$http_entity_type}rn"); 
fputs($fp, "內容長度: {$http_entity_length }rn"); 
fputs($fp, "連接:closernrn"); 
fputs($fp, $http_entity_body . "rnrn"); 
while (!feof($fp)) { 
getd $fp, 4096); 


fclose($fp); 
回顯$d; 

? > 
同樣地,讓我們來執行這個測試腳本

@php /phpinput_xmlrcp.php 
HTTP/1.1 200 OK 
日期:Thu, 08 Apr 2010 03:47:18 GMT )
X-Powered-By:PHP/5.1.6
內容長度:154
連接:關閉
內容類型:text/html;字元集=UTF-8 

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


------ -php:// input------------- 
 
 
jt_userinfo名稱> 
方法呼叫> 
執行這個腳本的時候,我們透過ngrep提取的http請求封包如下 

T 192.168.0.8:45570 -> 192.168.0.6:80 [AP] 
POST /phpinput_server.php HTTP/1.1..6
主機:text/html..內容長度:75..連接
tion:關閉.. .... jt_userinfo/name>. ....
同樣,我這樣也可以很容易發現:
1,http請求中的Content-Type是text/xml。它表示http請求中的body資料是xml資料格式。
2,服務端$_POST列印出來是一個空隊列,即和http實體主體不一致了。這上上個範例不一樣了,這裡的Content-Type是text/xml,而不是application/ x-www-form-urlencoded 
3,而php://inputData還是跟http實體body資料一致。原來php://inputData和$_POST資料不一致。

我們接下來看看透過GET方法提交表單資料的情況,php://input無法讀取到GET方法的表單資料?在這裡,稍微注意一下phpinput_server.php檔案成,將$_POST改成$_GET。

<?php 
//@file phpinput_server.php 
$raw_post_data = file_get_contents(&#39;php://input&#39;, &#39;r&#39;); 
echo "-------\$_GET------------------\n"; 
echo var_dump($_GET) . "\n"; 
echo "-------php://input-------------\n"; 
echo $raw_post_data . "\n"; 
?> 
<?php 
//@file phpinput_get.php 
$query_path = &#39;n=&#39; . urldecode(&#39;perfgeeks&#39;) . &#39;&p=&#39; . urldecode(&#39;7788&#39;); 
$host = &#39;192.168.0.6&#39;; 
$port = 80; 
$path = &#39;/phpinput_server.php&#39;; 
$d = &#39;&#39;; 
$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 
p-alive..User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) A 
ppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Re 
ferer: http://192.168.0.6/phpinput_server.php..Content-Length: 306..Ca 
che-Control: max-age=0..Origin: http://192.168.0.6..Content-Type: mult 
ipart/form-data; boundary=----WebKitFormBoundarybLQwkp4opIEZn1fA..Acce 
pt: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q 
=0.8,image/png,*/*;q=0.5..Accept-Encoding: gzip,deflate,sdch..Accept-L 
anguage: zh-CN,zh;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3..Cook 
ie: SESS3b0e658f87cf58240de13ab43a399df6=lju6o5bg8u04lv1ojugm2ccic6... 

## 
T 192.168.0.8:3981 -> 192.168.0.6:80 [AP] 
------WebKitFormBoundarybLQwkp4opIEZn1fA..Content-Disposition: form-da 
ta; name="n"....perfgeeks..------WebKitFormBoundarybLQwkp4opIEZn1fA..C 
ontent-Disposition: form-data; name="f"; filename="test.txt"..Content- 
Type: text/plain....i am file..multipart/form-data..------WebKitFormBo 
undarybLQwkp4opIEZn1fA--.. 
## 
从响应输出来比对,$_POST数据跟请求提交数据相符,即$_POST = array(‘n' => ‘perfgeeks')。这也跟http请求body中的数据相呼应,同时说明PHP把相应的数据填入$_POST全局变量。而php://input 输出为空,没有输出任何东西,尽管http请求数据包中body不为空。这表示,当Content-Type为multipart/form-data的 时候,即便http请求body中存在数据,php://input也为空,PHP此时,不会把数据填入php://input流。所以,可以确定: php://input不能用于读取enctype=multipart/form-data数据。 

我们再比较这次通过ngrep抓取的http请求数据包,我们会发现,最大不同的一 点是Content-Type后面跟了boundary定义了数据的分界符,bounday是随机生成的。另外一个大不一样的,就是http entity body中的数据组织结构不一样了。 

上一节,我们概述了,当Content-Type为application/x- www-form-urlencoded时,php://input和$_POST数据是“一致”的,为其它Content-Type的时候,php: //input和$_POST数据数据是不一致的。因为只有在Content-Type为application/x-www-form- urlencoded或者为multipart/form-data的时候,PHP才会将http请求数据包中的body相应部分数据填入$_POST全 局变量中,其它情况PHP都忽略。而php://input除了在数据类型为multipart/form-data之外为空外,其它情况都可能不为空。 通过这一节,我们更加明白了php://input与$_POST的区别与联系。所以,再次确认,php://input无法读取 enctype=multipart/form-data数据,当php://input遇到它时,永远为空,即便http entity body有数据。 
php://input VS $http_raw_post_data 

相信大家对php://input已经有一定深度地了解了。那 么$http_raw_post_data是什么呢?$http_raw_post_data是PHP内置的一个全局变量。它用于,PHP在无法识别的 Content-Type的情况下,将POST过来的数据原样地填入变量$http_raw_post_data。它同样无法读取Content- Type为multipart/form-data的POST数据。需要设置php.ini中的 always_populate_raw_post_data值为On,PHP才会总把POST数据填入变量$http_raw_post_data。 

把脚本phpinput_server.php改变一下,可以验证上述内容 

<?php 
$raw_post_data = file_get_contents(&#39;php://input&#39;, &#39;r&#39;); 
$rtn = ($raw_post_data == $HTTP_RAW_POST_DATA) ? 1 : 0; 
echo $rtn; 
?>

执行测试脚本 

@php phpinput_post.php 
@php phpinput_get.php 
@php phpinput_xmlrpc.php 

得出的结果输出都是一样的,即都为1,表示php://input和$HTTP_RAW_POST_DATA是相同的。至于对内存的压力,我们这里就不做细致地测试了。有兴趣的,可以通过xhprof进行测试和观察。 

以此,我们这节可以总结如下: 
1, php://input 可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据。但是,一般GET方法提交数据 时,http request entity body部分都为空。 
2,php://input 与$HTTP_RAW_POST_DATA读取的数据是一样的,都只读取Content-Type不为multipart/form-data的数据。 
学习笔记 

1,Coentent-Type仅在取值为application/x-www-data-urlencoded和multipart/form-data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST 
2,PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA 
3, 只有Coentent-Type不为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php://input,否则其它情况都会。填入的长度,由Coentent-Length指定。 
4,只有Content-Type为application/x-www-data-urlencoded时,php://input数据才跟$_POST数据相一致。 
5,php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini 
6,PHP会将PATH字段的query_path部分,填入全局变量$_GET。通常情况下,GET方法提交的http请求,body为空。

更多PHP输入流php://input介绍相关文章请关注PHP中文网!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境