所謂的敏感字元是指:在文章中含有不健康或反動類的資訊,影響社會的資訊,就會被視為敏感字元。因為有時候使用者輸入的敏感字元會無形中影響了程式的正確執行,著名的資料庫注入攻擊就是 在查詢條件裡面添加 資料庫的控制指令,從而達到攻擊者的目的。
這篇文章主要介紹了php表單敏感字元過濾類及其用法執行個體,詳細分析了表單產生與提交等環節針對敏感字元的過濾功能,是非常實用的技巧,需要的朋友可以參考下,具體分析如下:
/** * 表單產生驗證檔案 */ $_form = new formHtmlFind(); class formHtmlFind{ /** * 輸出表單函數 * $formKey 表單鍵 * $infoArray 更新時的原始資訊數組 */ public function formHtml($array,$infoArray='') { // 檢測數組是否存在 if(emptyempty($array))return false; $newform = null; // 資訊數組(更新資訊) $this->infoArray = !emptyempty($infoArray)?$infoArray:array(); $this->array['class'] = get_class_methods(get_class()); foreach ($array as $key =>$arr) { // 索引值轉換為純英文 $key = preg_replace("/[^a-z]/i",'',$key); // 產生表單 $newform .= $this->outputForm($arr,$key); } // 輸出表單 return $newform.$this->jsError(); } /** * 產生表單函數 */ private function outputForm($arr,$key) { $value = null; if(emptyempty($arr))return false; // input Type $type = $key; // input NAME $name = trim($arr[0]); // input 初始值 不包含多選,單選類 $value = (!emptyempty($this->infoArray[$name]))? trim($this->infoArray[$name]):trim($arr[1]); $value = emptyempty($this->post[$name])? $value :trim($this->post[$name]); // input Title $title = trim($arr[2]); // 樣式 $style = trim($arr[3]); if($key!=="hidden") { $dt = "<dt>{$title}</dt><dd>"; // js錯誤提示 $dd = "<tt id="J{$name}"></tt></dd>rn"; } return (!preg_match("/checkbox|select|radio/i",$key))? $dt.$this->newInput($type,$name,$value,$style,$title).$dd: $this->formSelect($type,$name,$arr[1],$title,$style); // 多選類 } /** * 提交資料檢測 */ public function postForm($array) { // 檢測數組是否存在 if(emptyempty($array)||emptyempty($_POST))return false; $this->post = $_POST; $this->array['class'] = get_class_methods(get_class()); foreach ($array as $key =>$arr) { // 索引值轉換為純英文 $key = preg_replace("/[^a-z]/i",'',$key); // 檢測 登出file類表單 if (!emptyempty($arr)&&'file' != $key)$newData[trim($arr[0])] = $this->postFind($arr,$key); } // 輸出表單 if(!emptyempty($this->error)) { return false; } else return $newData; } /** * 產生表單 */ private function newInput($type,$name,$value,$style,$title) { switch ($type) { case 'text': // 單行文本 return "<input type="text" name="{$name}" value="{$value}" {$style}/>"; break; case 'password': //密碼輸入 return "<input type="password" name="{$name}" {$style}/>"; break; case '': //多行文本 return "<textarea name="{$name}" {$style}/>{$value}</textarea>"; break; case 'hidden': // 隱藏 return "<input type="hidden" name="{$name}" value="{$value}" {$style}/>"; break; case 'file': // 檔案上傳 return "<input type= "file"name="{$name}" {$style}/>"; break; case 'submit': // 提交 return "<input type="submit" name="{$name}" value="$value" $style}/>"; break; default: return "{$type}類型錯誤!!!"; break; } } /** * 提交資訊檢測 * 錯誤返回error */ private function postFind($arr,$key) { if(emptyempty($arr))return false; $name = $title =$error =$find =$standard =null; // input NAME $name = trim($arr[0]); // input Title $title = trim($arr[2]); // 錯誤提示 $error = trim($arr[4]); // 檢測類型 Y N $find = trim($arr[5]); // 檢測標準 $standard = trim($arr[6]); // if(!emptyempty($standard))$this->error .=$this->ck_split($standard,$name,$title,$find,$error); // 轉換為字串 if(is_array($this->post[$name]))$this->post[$name] = implode(",",$this->post[$name]); // 轉義或其他轉化 $KKarray = array(); if(preg_match("/Y|N/is",$find)) { $KKarray = split("_", $find); // 轉義或過濾 $escape_filter = (!emptyempty($KKarray[1]))?'ck_'.$KKarray[1]:''; // 輸出通過檢測的合法資料 $data = ($escape_filter)?$this->$escape_filter($this->post[$name]):$this->post[$name]; } else $data = ""; // 輸出新的資料 return $data; } /** * 多選類表單產生 */ private function formSelect($type,$name,$value,$title,$style) { $outform = null; // 觸發更新和提交動作時的初始 $nowvalue = (!emptyempty($this->post[$name]))?$this->post[$name]:$this->infoarray[$name]; // 相容多選的識別,轉為數組 if(!emptyempty($nowvalue))$valueArray = explode(",",$nowvalue); // 選項標題 if(is_array($title)) { array_unshift($title,'選擇'); $titarray = array_values($title); }else $titarray = explode("|",$title); // 選項值 if(is_array($value)) { array_unshift($value,'選擇'); $valarray = array_keys($value); if(emptyempty($title))$titarray = array_values($value); } else $valarray = explode("|",$value); // 取消表單的初始預設值 if(!emptyempty($this->post)&&!emptyempty($this->infoArray))$value = preg_replace("/Y_/i",'',$value); foreach ($valarray as $key =>$varl) { // 非預設的識別 if(!emptyempty($valueArray))$select = (in_array($varl,$valueArray))?'Y':''; // 判斷是否為預設 else $select = (eregi("Y_",$varl))? 'Y':''; if($key >'0') { $_title=($titarray[$key])? $titarray[$key]:$title; switch ($type) { case 'select': if('Y' == $select)$select = 'selected'; $outform .= sprintf("<option %s value="%s"/>%s</option>rn" ,$select,preg_replace("/Y_/i",'',$varl),$_title); break; case 'radio': if('Y' == $select)$select = 'checked'; $outform .= sprintf("<label>%s<input %s type="radio" name="%s" value="%s" %s/></label>rn", $_title,$select,$name,$varl,$style); break; case 'checkbox': if('Y' == $select)$select = 'checked'; $outform .= sprintf("<label>%s<input %s type="checkbox" name="%s[]" value="%s" %s/></label>rn",$_title,$select,$name,$varl,$style); break; } $select =null; } } // 下拉選擇 if($type =='select')$outform = sprintf('<select name="%s" %s>%s</select>',$name,$style,$outform); return sprintf("<dt>%s</dt><dd>%s<tt id="J%s"></tt></dd>rn",$titarray[0],$outform,$name); } /** * 表單驗證 及全部 ck_類函數 */ private function ck_split($standard,$name,$title,$find,$error) { // 非必填預設跳過 if(eregi('N',$find) && emptyempty($this->post[$name]))return false; // 必填預設檢測 if(eregi('Y',$find) && emptyempty($this->post[$name]))return "["J{$name}","$error"],"; $t_error = null; // 多項檢測 $arr = explode(',',$standard); // POST資料檢測 if(!emptyempty($arr))foreach ($arr as $var) { if(trim($var)!='') { switch ($this->post) { case is_array($this->post[$name]): // 數組類的檢測 foreach ($this->post[$name] as $_var) { $t_error.= ($this->ck_open($_var,trim($var)))?"":$error; if($t_error)break; } break; default: $t_error.= ($this->ck_open($this->post[$name],trim($var)))?"":$error; break; } if($t_error)break; } } return ($t_error)? "["J{$name}","$t_error"],":""; } // 函數調用 private function ck_open($string,$str) { $functi = $this->ck_detected($str); return ($this->$functi($string,$str))? true:false; } // 類型判斷 private function ck_detected($str) { $detect = (eregi("^[a-zA-Z]*$",$str))? "{$str}Detect":'lengthDetect'; if(!in_array($detect,$this->array['class'])) { location('index.php',$ck,' Lack of function !!!'); } return $detect; } //-------------------------------------以下為檢測函數可外部調用 // 長度 public function lengthDetect($string,$str){ $len = split('-',trim($str)); return (strlen($string) > ($len[0]-1) && strlen($string) < ($len[1]+1))? true:false; } // 價格 public function moneyDetect($str){ return preg_match("/^(-|+)?d+(.d+)?$/",$str); } // 郵件 public function emailDetect($str){ return preg_match("/^w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$/", $str); } // 網址 public function urlDetect($str){ return preg_match("/^http://[A-Za-z0-9]+.[A-Za-z0-9]+[/=?%-&_~`@[]':+!]*([^<>"])*$/", $str); } // 數字型 public function numDetect($str){ return is_numeric($str); } // 中文 public function cnDetect($str){ return preg_match("/^[x7f-xff]+$/", $str); } // 字母 public function enDetect($str){ return preg_match("/^[A-Za-z]+$/", $str); } // 數字字母混合 public function numenDetect($str){ return preg_match("/^([a-zA-Z0-9_-])+$/",$str); } // 電話號碼 public function telDetect($str){ return ereg("^[+]?[0-9]+([xX-][0-9]+)*$", $str); } // 敏感詞 public function keyDetect($str){ return (!preg_match("/$badkey/i",$str)); } //-----------------------------------------------------輸出 // 字元替換 public function ck_filter($str){ $str=(is_array($str))? implode(",",$str):$str; $str=nl2br($str); //將斷行符號替換為<br> $str=htmlspecialchars($str); //將特殊字元轉成 HTML 格式。 //$str=str_replace(array(" ",'<? '),array(" ",'< ?'),$str); //替換空格替換為 return $str; } // 轉義 function ck_escape($str) { if (!get_magic_quotes_gpc())return addslashes($str); return $str; } // MD5加密 public function ck_md5($str){ return MD5($str); } // base64加密 public function ck_base64($str){ return base64_encode($str); } // 時間 function ck_time($str){ // time_r() 來在公用函數檔案 if(!is_numeric($str)) { return time_r($str); } else return $str; } // 有條件登出(數字) public function ck_cancel($str){ return (!is_numeric($str))? $str:""; } // 無條件登出 public function ck_delete(){ return null; } // js錯誤提示 private function jsError() { if(emptyempty($this->error))return false; return " <script language=javascript> rn var error = new Array(".trim($this->error,',')."); rn for (i=0; i < error.length; i++){ rn document.getElementById(error[0]).innerHTML=error[1]; }rn </script> "; } } // 示範: $form[1] =array( 'text'=>array('title','','產品名稱','size=40','產品名稱不可缺少!','Y','cn,1-30'), 'text1'=>array('categories','','產品名稱','','','Y_base64'), 'select'=>array('superiors','||1|2|Y_3','產品類別|選擇|1|2|3','','必選項','Y'), 'radio'=>array('superiors1','|1|Y_2|3','產品xun|產品1|產品2|產品3','','必選項','Y'), 'checkbox'=>array('superiors2',array(1=>'11',2=>'22',3=>'33'),'','','必選項','Y'), 'file'=>array('ddd','','檔案'), ); $form =array ( 'login' => array ( 'text' => array ( 0 => 'user', 1 => '', 2 => '使用者名稱', 3 => 'size=20', 4 => '!', 5 => 'Y', 6 => 'numen,6-12', ), 'password' => array ( 0 => 'pass', 1 => '', 2 => '密 碼', 3 => 'size=22', 4 => '密碼格式錯誤!', 5 => 'Y_md5', 6 => 'numen,6-12', ), 'radio' => array ( 0 => 'time', 1 => '|7200|3600|1800', 2 => 'cookies有效時間|2小時|1小時|30分鐘', 3 => '', 4 => '', 5 => 'N_delete', 6 => '', ), ), ); // 表單提交效驗 $past = $_form->postForm($form['login']); $dd = array('title'=>'標題','categories'=>'類別'); // $dd 為已有的資訊(如更新時的資訊輸出) POST資料位元內部處理具有優先權if(!emptyempty($past)) { echo "<pre>"; print_r($past); echo"</pre>"; } echo '<form method="POST" NAME="PostTopic" action="" enctype="multipart/form-data" style="margin:0px;">'; echo $_form->formHtml($form['login'],$dd); echo '<input type="submit" value="Y" name="B1"></form>';