iT邦幫忙

3

[PHP]消毒變數的利器,filter_var和filter_var_array

php

只要有使用者輸入的地方,都不能大意,因為一不小心就有可能被植入惡意程式碼,所以消毒就變得非常重要,不過自己處理難免百密一疏,所幸PHP從5.2開始提供內建方法

就是filter_varfilter_var_array,前者處理單一變數,後者當然是處理陣列囉

搭配不同的參數,就可以消毒不同的型態,數字甚至可以自訂範圍,使用上非常的靈活,不過我在使用上,有一個固定的模式,就是接收表單後,要檢查各個值是否符合規定,以及是否有缺值,因為實在是很懶得針對每個去寫檢查,想要一坨一次檢查

想當然就是用filter_var_array直接檢查POST或GET了,但是發現每個值都要另外處理參數,實在是太麻煩了,經過評估發現我大部分都是文字比較多,所以就寫了一個方法,讓預設處理是FILTER_SANITIZE_STRING,若是數字或其他的再特別指定

至於要怎麼知道有違法的值,有個參數很好用,就是FILTER_NULL_ON_FAILURE,失敗自動回傳null,我再檢查結果陣列內有任何是null,如果有就整陀不能用啦

/**
* 消毒變數,未指定的key依照預設的方式消毒
* @param array $data 來源陣列
* @param mixed $args 指定各數值的消毒方式
* @param filter_flag $default_filter 針對未指定的值採用的消毒方式
* 
* @return mixed 已消毒的array,若某個值過濾失敗則回傳false
*/
function sanitize_var($data, $args=array(), $default_filter = FILTER_SANITIZE_STRING){
	foreach($data as $key=>$value){
		if(!array_key_exists($key, $args)){
			$args[$key] = array("filter"=>$default_filter, "flags"=>FILTER_NULL_ON_FAILURE);
		}else{
			if(is_array($args[$key])){
			  //若原本有指定參數,則加上FILTER_NULL_ON_FAILURE,若沒有則指定FILTER_NULL_ON_FAILURE
				if(array_key_exists("flags", $args[$key])){
					$args[$key]["flags"] |= FILTER_NULL_ON_FAILURE;
				}else{
					$args[$key]["flags"] = FILTER_NULL_ON_FAILURE;
				}
			}else{
				$tmp_filter = $args[$key];
				$args[$key] = array("filter"=>$tmp_filter, "flags"=>FILTER_NULL_ON_FAILURE);
			}
		}
	}
	$result = filter_var_array($data, $args);
	foreach($result as $key=>$value){
		if(is_null($value)){
			return FALSE;
		}
	}
	return $result;
}

//account和password兩個是必要值,若有缺則會返回false
$data = sanitize_var($_POST, array('account'=>FILTER_SANITIZE_STRING, 'password'=>FILTER_SANITIZE_STRING));
if($data){
  //do something
}else{
  //value is invalid
}

//不指定必要值,預設會將包含的變數預設以FILTER_SANITIZE_STRING進行消毒
$data = sanitize_var($_GET);
//直接使用$data內的值

感覺是不是方便了不少,一次解決缺值檢查跟類型消毒,如果有更好的方法或改良,歡迎提供出來參考參考,大家互相漏氣求進步~


1 則留言

0
小魚
iT邦大師 1 級 ‧ 2019-07-15 20:51:30

這到底是要防什麼?
我輸入最基本的SQL Injection
http://localhost/practice2/test.php?test=' 1 = 1 OR '
好像還是跑出

' 1 = 1 OR '
木澤 iT邦新手 5 級 ‧ 2019-07-16 14:53:34 檢舉

這個function算是簡化使用PHP內建的消毒方法,並且順便檢查該key是否有值,幫忙限定GET或POST的參數,詳細的參數列表請參考Sanitize filters

消毒可以去掉一些有危害的字元,或者針對數字範圍作限定以及限定EMAIL格式等等,至於SQL Injection的部分,最好的方法還是Prepared Statement

小魚 iT邦大師 1 級 ‧ 2019-07-16 15:46:10 檢舉

原來如此, 了解, 謝謝.

我要留言

立即登入留言