一顷级、php過(guò)濾器
PHP 過(guò)濾器用于驗(yàn)證和過(guò)濾來(lái)自非安全來(lái)源的數(shù)據(jù)凫乖,比如用戶的輸入。測(cè)試弓颈、驗(yàn)證和過(guò)濾用戶輸入或自定義數(shù)據(jù)是任何 Web 應(yīng)用程序的重要組成部分帽芽。PHP 的過(guò)濾器擴(kuò)展的設(shè)計(jì)目的是使數(shù)據(jù)過(guò)濾更輕松快捷。
幾乎所有的 Web 應(yīng)用程序都依賴外部的輸入翔冀。這些數(shù)據(jù)通常來(lái)自用戶或其他應(yīng)用程序(比如 web 服務(wù))导街。通過(guò)使用過(guò)濾器,您能夠確保應(yīng)用程序獲得正確的輸入類型纤子。
什么是外部數(shù)據(jù)搬瑰?來(lái)自表單的輸入數(shù)據(jù)? ? Cookies? ? Web services data? ? 服務(wù)器變量
? 數(shù)據(jù)庫(kù)查詢結(jié)果
您應(yīng)該始終對(duì)外部數(shù)據(jù)進(jìn)行過(guò)濾!輸入過(guò)濾是最重要的應(yīng)用程序安全課題之一控硼。
如需過(guò)濾變量泽论,請(qǐng)使用下面的過(guò)濾器函數(shù)之一:
filter_var() - 通過(guò)一個(gè)指定的過(guò)濾器來(lái)過(guò)濾單一的變量
filter_var_array() - 通過(guò)相同的或不同的過(guò)濾器來(lái)過(guò)濾多個(gè)變量
filter_input - 獲取一個(gè)輸入變量,并對(duì)它進(jìn)行過(guò)濾
filter_input_array - 獲取多個(gè)輸入變量卡乾,并通過(guò)相同的或不同的過(guò)濾器對(duì)它們進(jìn)行過(guò)濾
<?php
$int = 123;
if(!filter_var($int, FILTER_VALIDATE_INT))
{
echo? ("Integer is not valid");
}
else
{
echo?? ("Integer is valid");
}
?>
上面的代碼使用了 "FILTER_VALIDATE_INT" 過(guò)濾器來(lái)過(guò)濾變量佩厚。由于這個(gè)整數(shù)是合法的,因此上面的代碼將輸出:"Integer is valid"说订。
如果我們嘗試使用一個(gè)非整數(shù)的變量(比如 "123abc")抄瓦,則將輸出:"Integer is not valid"。
有兩種過(guò)濾器:
Validating 過(guò)濾器:
用于驗(yàn)證用戶輸入
嚴(yán)格的格式規(guī)則(比如 URL 或 E-Mail 驗(yàn)證)
如果成功則返回預(yù)期的類型陶冷,如果失敗則返回 FALSE
Sanitizing 過(guò)濾器:
用于允許或禁止字符串中指定的字符Are used to allow or disallow specified characters in a string
無(wú)數(shù)據(jù)格式規(guī)則
始終返回字符串
選項(xiàng)和標(biāo)志
選項(xiàng)和標(biāo)志用于向指定的過(guò)濾器添加額外的過(guò)濾選項(xiàng)钙姊。
不同的過(guò)濾器有不同的選項(xiàng)和標(biāo)志。
在下面的實(shí)例中埂伦,我們用 filter_var() 和 "min_range" 以及 "max_range" 選項(xiàng)驗(yàn)證了一個(gè)整數(shù):
<?php
$var=300;
$int_options = array(
"options"=>array
(
"min_range"=>0,
"max_range"=>256
)
);
if(!filter_var($var, FILTER_VALIDATE_INT, $int_options))
{
echo("Integer is not valid");
}
else
{
echo("Integer is valid");
}
?>
就像上面的代碼一樣煞额,選項(xiàng)必須放入一個(gè)名為 "options" 的相關(guān)數(shù)組中。如果使用標(biāo)志沾谜,則不需在數(shù)組內(nèi)膊毁。
由于整數(shù)是 "300",它不在指定的范圍內(nèi)基跑,以上代碼的輸出將是 "Integer is not valid"婚温。
驗(yàn)證輸入
讓我們?cè)囍?yàn)證來(lái)自表單的輸入。
我們需要做的第一件事情是確認(rèn)是否存在我們正在查找的輸入數(shù)據(jù)媳否。
然后我們用 filter_input() 函數(shù)過(guò)濾輸入的數(shù)據(jù)栅螟。
在下面的實(shí)例中荆秦,輸入變量 "email" 被傳到 PHP 頁(yè)面:
<?php
if(!filter_has_var(INPUT_GET, "email"))
{
echo("Input type does not exist");
}
else
{
if (!filter_input(INPUT_GET, "email", FILTER_VALIDATE_EMAIL))
{
echo "E-Mail is not valid";
}
else
{
echo "E-Mail is valid";
}
}
?>
上面的實(shí)例有一個(gè)通過(guò) "GET" 方法傳送的輸入變量 (email):檢測(cè)是否存在 "GET" 類型的 "email" 輸入變量,如果存在輸入變量,檢測(cè)它是否是有效的 e-mail 地址
凈化輸入
讓我們?cè)囍謇硪幌聫谋韱蝹鱽?lái)的 URL力图。
首先步绸,我們要確認(rèn)是否存在我們正在查找的輸入數(shù)據(jù)。
然后吃媒,我們用 filter_input() 函數(shù)來(lái)凈化輸入數(shù)據(jù)瓤介。
在下面的實(shí)例中,輸入變量 "url" 被傳到 PHP 頁(yè)面:
<?php
f(!filter_has_var(INPUT_POST, "url"))
{
echo("Input type does not exist");
}
else
{
$url = filter_input(INPUT_POST,
"url", FILTER_SANITIZE_URL);
}
?>
上面的實(shí)例有一個(gè)通過(guò) "POST" 方法傳送的輸入變量 (url):
檢測(cè)是否存在 "POST" 類型的 "url" 輸入變量
如果存在此輸入變量赘那,對(duì)其進(jìn)行凈化(刪除非法字符)刑桑,并將其存儲(chǔ)在 $url 變量中
假如輸入變量是一個(gè)類似這樣的字符串:"http://www.W3C??Sch??ool.cc/",則凈化后的 $url 變量如下所示:
http://www.W3CSchool.cc/
過(guò)濾多個(gè)輸入
表單通常由多個(gè)輸入字段組成漓概。為了避免對(duì) filter_var 或 filter_input 函數(shù)重復(fù)調(diào)用漾月,我們可以使用 filter_var_array 或 the filter_input_array 函數(shù)。
在本例中胃珍,我們使用 filter_input_array() 函數(shù)來(lái)過(guò)濾三個(gè) GET 變量梁肿。接收到的 GET 變量是一個(gè)名字、一個(gè)年齡以及一個(gè) e-mail 地址:
<?php
$filters = array
(
"name" => array
(
"filter"=>FILTER_SANITIZE_STRING
),
"age" => array
(
"filter"=>FILTER_VALIDATE_INT,
"options"=>array
(
"min_range"=>1,
"max_range"=>120
)
),
"email"=> FILTER_VALIDATE_EMAIL
);
$result = filter_input_array(INPUT_GET, $filters);
if (!$result["age"])
{
echo("Age must be a number between 1 and 120.
");
}
elseif(!$result["email"])
{
echo("E-Mail is not valid.
");
}
else
{
echo("User input is valid");
}
?>
上面的實(shí)例有三個(gè)通過(guò) "GET" 方法傳送的輸入變量 (name觅彰、age 和 email):
設(shè)置一個(gè)數(shù)組吩蔑,其中包含了輸入變量的名稱和用于指定的輸入變量的過(guò)濾器
調(diào)用 filter_input_array() 函數(shù),參數(shù)包括 GET 輸入變量及剛才設(shè)置的數(shù)組
檢測(cè) $result 變量中的 "age" 和 "email" 變量是否有非法的輸入填抬。(如果存在非法輸入烛芬,在使用 filter_input_array() 函數(shù)之后,輸入變量為 FALSE飒责。)
filter_input_array() 函數(shù)的第二個(gè)參數(shù)可以是數(shù)組或單一過(guò)濾器的 ID赘娄。
如果該參數(shù)是單一過(guò)濾器的 ID,那么這個(gè)指定的過(guò)濾器會(huì)過(guò)濾輸入數(shù)組中所有的值宏蛉。
如果該參數(shù)是一個(gè)數(shù)組遣臼,那么此數(shù)組必須遵循下面的規(guī)則:
必須是一個(gè)關(guān)聯(lián)數(shù)組,其中包含的輸入變量是數(shù)組的鍵(比如 "age" 輸入變量)
此數(shù)組的值必須是過(guò)濾器的 ID 拾并,或者是規(guī)定了過(guò)濾器揍堰、標(biāo)志和選項(xiàng)的數(shù)組
使用 Filter Callback
通過(guò)使用 FILTER_CALLBACK 過(guò)濾器,可以調(diào)用自定義的函數(shù)嗅义,把它作為一個(gè)過(guò)濾器來(lái)使用屏歹。這樣,我們就擁有了數(shù)據(jù)過(guò)濾的完全控制權(quán)之碗。
您可以創(chuàng)建自己的自定義函數(shù)蝙眶,也可以使用已存在的 PHP 函數(shù)。
將您準(zhǔn)備用到的過(guò)濾器的函數(shù)继控,按指定選項(xiàng)的規(guī)定方法進(jìn)行規(guī)定械馆。在關(guān)聯(lián)數(shù)組中胖眷,帶有名稱 "options"武通。
在下面的實(shí)例中霹崎,我們使用了一個(gè)自定義的函數(shù)把所有 "_" 轉(zhuǎn)換為空格:
<?php
function convertSpace($string)
{
return str_replace("_", " ", $string);
}
$string = "Peter_is_a_great_guy!";
echo filter_var($string, FILTER_CALLBACK,
array("options"=>"convertSpace"));
?>
上面代碼的結(jié)果如下所示:
Peter is a great guy!
上面的實(shí)例把所有 "_" 轉(zhuǎn)換成空格:創(chuàng)建一個(gè)把 "_" 替換為空格的函數(shù),調(diào)用 filter_var() 函數(shù),它的參數(shù)是 FILTER_CALLBACK 過(guò)濾器以及包含我們的函數(shù)的數(shù)組
二冶忱、PHP中header的用法總結(jié)
header()函數(shù)的作用是:發(fā)送一個(gè)原始 HTTP 標(biāo)頭[Http Header]到客戶端尾菇。
標(biāo)頭 (header) 是服務(wù)器以 HTTP 協(xié)義傳 HTML 資料到瀏覽器前所送出的字串,在標(biāo)頭
與 HTML 文件之間尚需空一行分隔囚枪。有關(guān) HTTP 的詳細(xì)說(shuō)明派诬,可以參 RFC 2068 官方文件
(http://www.w3.org/Protocols/rfc2068/rfc2068)。
在 PHP 中送回 HTML 資料前链沼,需先 傳完所有的標(biāo)頭默赂。
使用范例:
范例一: 本例使瀏覽器重定向到 PHP 的官方網(wǎng)站。
<?php
Header("Location:http://www.php.net";);
exit;//在每個(gè)重定向之后都必須加上“exit",避免發(fā)生錯(cuò)誤后括勺,繼續(xù)執(zhí)行缆八。
?>
<?php
header("refresh:3;url=http://axgle.za.net");
print('正在加載,請(qǐng)稍等...
三秒后自動(dòng)跳轉(zhuǎn)~~~');
header重定向 就等價(jià)于替用戶在地址欄輸入url
?>
范例二:禁止頁(yè)面在IE中緩存
要使用者每次都能得到最新的資料疾捍,而不是 Proxy 或 cache中的資料奈辰,可以使用下列的標(biāo)頭
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s') .' GMT');
header('Cache-Control: no-store, no-cache,
must-revalidate');
header('Cache-Control: post-check=0,
pre-check=0',false);
header('Pragma: no-cache');//兼容http1.0和https
?>
CacheControl = no-cache
Pragma=no-cache
Expires = -1
Expires是個(gè)好東東,如果服務(wù)器上的網(wǎng)頁(yè)經(jīng)常變化乱豆,就把它設(shè)置為-1奖恰,表示立即過(guò)期。如果一個(gè)網(wǎng)頁(yè)每天凌晨1點(diǎn)更新宛裕,可以把Expires設(shè)置為第二天的凌晨1點(diǎn)瑟啃。
當(dāng)HTTP1.1服務(wù)器指定CacheControl = no-cache時(shí),瀏覽器就不會(huì)緩存該網(wǎng)頁(yè)揩尸。
舊式 HTTP 1.0 服務(wù)器不能使用 Cache-Control 標(biāo)題蛹屿。所以為了向后兼容 HTTP 1.0服務(wù)器,IE使用Pragma:no-cache 標(biāo)題對(duì) HTTP 提供特殊支持疲酌。
如果客戶端通過(guò)安全連接 (https://) 與服務(wù)器通訊蜡峰,且服務(wù)器在響應(yīng)中返回 Pragma:no-cache 標(biāo)題,則Internet Explorer 不會(huì)緩存此響應(yīng)朗恳。
注意:Pragma:no-cache僅當(dāng)在安全連接中使用時(shí)才防止緩存湿颅,如果在非安全頁(yè)中使用,處理方式與 Expires:-1相同粥诫,該頁(yè)將被緩存油航,但被標(biāo)記為立即過(guò)期。
http-equiv meta標(biāo)記:
html頁(yè)面中可以用http-equiv meta來(lái)標(biāo)記指定的http消息頭部怀浆。老版本的IE可能不支持htmlmeta標(biāo)記谊囚,所以最好使用http消息頭部來(lái)禁用緩存怕享。
范例三: 讓使用者的瀏覽器出現(xiàn)找不到檔案的信息。
網(wǎng)上很多資料這樣寫:php的函數(shù)header()可以向?yàn)g覽器發(fā)送Status標(biāo)頭镰踏,
如 header(”Status: 404 Not Found”)函筋。
但是我發(fā)現(xiàn)實(shí)際上瀏覽器返回的響應(yīng)卻是:
HTTP/1.x 200 OK
Date: Thu, 03 Aug 2006 07:49:11 GMT
Server: Apache/2.0.55 (Win32) PHP/5.0.5
X-Powered-By: PHP/5.0.5
Status: 404 Not Found
Content-Length: 0
Keep-Alive: timeout=15, max=98
Connection: Keep-Alive
Content-Type: text/html
查了一些資料,正確的寫法是:
header(”http/1.1 404 Not
Found”);
第一部分為HTTP協(xié)議的版本(HTTP-Version)奠伪;第二部分為狀態(tài)代碼(Status)跌帐;第三部分為原因短語(yǔ)(Reason-Phrase)。
范例四:讓使用者下載檔案( 隱藏文件的位置 )
html標(biāo)簽 就可以實(shí)現(xiàn)普通文件下載绊率。如果為了保密文件谨敛,就不能把文件鏈接告訴別人,可以用header函數(shù)實(shí)現(xiàn)文件下載滤否。
header("Content-type: application/x-gzip");
header("Content-Disposition: attachment; filename=文件名\");
header("Content-Description: PHP3 Generated Data");
?>
范例四:header函數(shù)前輸入內(nèi)容
一般來(lái)說(shuō)在header函數(shù)前不能輸出html內(nèi)容脸狸,類似的還有setcookie() 和 session函數(shù),這些函數(shù)需要在輸出流中增加消息頭部信息藐俺。如果在header()執(zhí)行之前有echo等語(yǔ)句炊甲,當(dāng)后面遇到header()時(shí),就會(huì)報(bào)出“Warning: Cannot modify header information - headers already sentby….”錯(cuò)誤紊搪。就是說(shuō)在這些函數(shù)的前面不能有任何文字蜜葱、空行、回車等耀石,而且最好在header()函數(shù)后加上exit()函數(shù)牵囤。例如下面的錯(cuò)誤寫法,在兩個(gè)php代碼段之間有一個(gè)空行:
//some code here
?>
//這里應(yīng)該是一個(gè)空行
header(”http/1.1 403 Forbidden”);
exit();
?>
原因是:PHP腳本開始執(zhí)行 時(shí),它可以同時(shí)發(fā)送http消息頭部(標(biāo)題)信息和主體信息. http消息頭部(來(lái)自 header() 或SetCookie() 函數(shù))并不會(huì)立即發(fā)送,相反,它被保存到一個(gè)列表中. 這樣就可以允許你修改標(biāo)題信息,包括缺省的標(biāo)題(例如Content-Type 標(biāo)題).但是,一旦腳本發(fā)送了任何非標(biāo)題的輸出(例如,使用 HTML 或 print()調(diào)用),那么PHP就必須先發(fā)送完所有的Header,然后終止 HTTPheader.而后繼續(xù)發(fā)送主體數(shù)據(jù).從這時(shí)開始,任何添加或修改Header信息的試圖都是不允許的,并會(huì)發(fā)送上述的錯(cuò)誤消息之一滞伟。
解決辦法:
修改php.ini打開緩存(output_buffering),或者在程序中使用緩存函數(shù)ob_start()揭鳞,ob_end_flush()等。原理是:output_buffering被啟用時(shí),在腳本發(fā)送輸出時(shí)梆奈,PHP并不發(fā)送HTTPheader野崇。相反,它將此輸出通過(guò)管道(pipe)輸入到動(dòng)態(tài)增加的緩存中(只能在PHP4.0中使用亩钟,它具有中央化的輸出機(jī)制)乓梨。你仍然可以修改/添加header,或者設(shè)置cookie清酥,因?yàn)閔eader實(shí)際上并沒(méi)有發(fā)送扶镀。當(dāng)全部腳本終止時(shí),PHP將自動(dòng)發(fā)送HTTP header到瀏覽器焰轻,然后再發(fā)送輸出緩沖中的內(nèi)容臭觉。
PHP 手冊(cè)實(shí)例應(yīng)用
1:您可以使用heder命令,強(qiáng)制使瀏覽器使用新鮮的內(nèi)容(無(wú)緩存) 。
也可以給網(wǎng)址增加了一個(gè)唯一的編號(hào)蝠筑,使其每次都讀取新的內(nèi)容狞膘,避免緩存。
example:
<?php
print"<img src='yourfile.jpg'>";//通常讀取的是緩存文件
?>
<?php
print"<img src='yourfile.jpg?".time()."'>";//增加了唯一的編號(hào)什乙,使瀏覽器重新請(qǐng)求
w//print"<img src='yourfile.jpg?".rand(100,999)."'>";
?>
2: 下面是個(gè)很好的函數(shù)挽封,將圖片傳送給瀏覽器顯示。
<?php
function PE_img_by_path($PE_imgpath = "")
{
if(file_exists($PE_imgpath)) {
$PE_imgarray = pathinfo($PE_imgpath);
$iconcontent = file_get_contents($PE_imgpath);
header("Content-type: image/" . $PE_imgarray["extension"]);
header('Content-length: ' . strlen($iconcontent));
echo $iconcontent;
die(0);
}
returnfalse;
}
?>
更多的實(shí)例:
<?php
// ok
header('HTTP/1.1 200 OK');
//設(shè)置一個(gè)404頭:
header('HTTP/1.1 404 Not Found');
//設(shè)置地址被永久的重定向
header('HTTP/1.1 301 Moved Permanently');
//轉(zhuǎn)到一個(gè)新地址
header('Location:http://www.example.org/');
//文件延遲轉(zhuǎn)向:
header('Refresh: 10; url=http://www.example.org/');
print 'You will be redirected in 10 seconds';
//當(dāng)然稳强,也可以使用html語(yǔ)法實(shí)現(xiàn)
//<meta http-equiv="refresh" ? content="10;http://www.example.org/ />
// override X-Powered-By: PHP:
header('X-Powered-By: PHP/4.4.0');
header('X-Powered-By: Brain/0.6b');
//文檔語(yǔ)言
header('Content-language: en');
//告訴瀏覽器最后一次修改時(shí)間
$time = time() - 60; // or filemtime($fn), etc
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).'GMT');
//告訴瀏覽器文檔內(nèi)容沒(méi)有發(fā)生改變
header('HTTP/1.1 304 Not Modified');
//設(shè)置內(nèi)容長(zhǎng)度
header('Content-Length: 1234');
//設(shè)置為一個(gè)下載類型
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment;filename="example.zip"');
header('Content-Transfer-Encoding: binary');
// load the file to send:
readfile('example.zip');
// 對(duì)當(dāng)前文檔禁用緩存
header('Cache-Control: no-cache, no-store, max-age=0,must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in thepast
header('Pragma: no-cache');
//設(shè)置內(nèi)容類型:
header('Content-Type: text/html; charset=iso-8859-1');
header('Content-Type: text/html; charset=utf-8');
header('Content-Type: text/plain'); //純文本格式
header('Content-Type: image/jpeg'); //JPG圖片
header('Content-Type: application/zip'); // ZIP文件
header('Content-Type: application/pdf'); // PDF文件
header('Content-Type: audio/mpeg'); // 音頻文件
header('Content-Type: application/x-shockwave-flash');//Flash動(dòng)畫
//顯示登陸對(duì)話框
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Basic realm="Top Secret"');
print 'Text that will be displayed if the user hits cancel or';
print 'enters wrong login data';
?>