返回首页 我的新博客

PHP防注入攻击过滤HTML代码函数

<?php 
/***** 说明: 
* 当附合要求的参数传递进filter函数后,filter()函数首先 
* 把要字串中所有要过滤的标签$tag通过preg_match_all() 
* 取出来,然后循环preg_match_all的匹配数组,通过preg_split() 
* 函数分割每个标签为 "左边属性" = "右边值"的形式,再从要保 
* 留的属性数组中循环,将preg_split()匹配的内容对应取出,构成 
* 可以替换的值,后最通过str_replcae()替换掉字串中相应的标签 
* 函数列表: 
* function filter(&$str,$tag,$keep_attribute) 
* function match($reg,&$str,$arr) 
* function show($str,$title=’’,$debug = True) 
* 使用示例: 
* //取得搜狐新闻首页 
* $str = @file_get_content("http://news。sohu.com"); 
* //过滤 
* filter($str,’a’,’href,target,alt’); 
* filter($str,’p’,’align’); 
* show($str,’过滤后的内容’); 
*************************************************/ 

$start_time = array_sum(explode(" ",microtime())); 

$str = <<< HTML 
<A style="a" target=_blank href=’http://www。a.com’ xxx=xadsfa alt="a a a" style="aa">site a</A> 
<A alt=’b b b’ xxx=xadsfa target=_blank href=’http://www。b.com’ style="b" style="bb">site b</A> 
<A xxx=xadsfa style="c" href=’http://www。c.com’ target=_blank alt=c c c style="cc">site c</A> 
<A style="d" href=’http://www。d.com’ xxx=xadsfa alt=d d d target=_blank style="dd">site d</A> 
<A target=_blank style="e" xxx=xadsfa style="ee" alt=e e e href=’http://www。e.com’>site e</A> 

<p align=right style="font-size:10px">adasdfasdf</p> 
<p style="font-color:red;" align=’left’>asdfasdfasdfasdf</p> 
<p align=left right center>asdfasdfasdf</p> 

<font color="red" alt=adasd adsasd>asdfadsfasdf</font> 
<font align=’left’ color=red>asdfasdfadf</font> 
<font align=left right color=red black>asdfasdf</font> 
HTML; 

//显示原字串 
show($str,’Html’); 

/***/ 
//过滤 
filter($str,’a’,’href,target,alt’); 
filter($str,’p’,’align’); 
filter($str,’font’,’color,alt’); 

//显示过滤后的内容 
show($str,’Result’); 

//脚本运行时间 
$run_time = array_sum(explode(" ",microtime())) - $start_time; 
echo(’<center>Script Run Time: ’.$run_time.’</center>’); 

/** 
* 说明:过滤HTML字串 
* 参数: 
* $str : 要过滤的HTML字串 
* $tag : 过滤的标签类型 
* $keep_attribute : 
* 要保留的属性,此参数形式可为 
* href 
* href,target,alt 
* array(’href’,’target’,’alt’) 
*/ 
function filter(&$str,$tag,$keep_attribute) { 

//检查要保留的属性的参数传递方式 
if(!is_array($keep_attribute)) { 
//没有传递数组进来时判断参数是否包含,号 
if(strpos($keep_attribute,’,’)) { 
//包含,号时,切分参数串为数组 
$keep_attribute = explode(’,’,$keep_attribute); 
}else { 
//纯字串,构造数组 
$keep_attribute = array($keep_attribute); 


echo("·过滤[$tag]标签,保留属性:".implode(’,’,$keep_attribute).’<br>’); 

//取得所有要处理的标记 
$pattern = "/<$tag(.*)<\/$tag>/i"; 
preg_match_all($pattern,$str,$out); 

//循环处理每个标记 
foreach($out[1] as $key => $val) { 
//取得a标记中有几个= 
$cnt = preg_split(’/ *=/i’,$val); 
$cnt = count($cnt) -1; 

//构造匹配正则 
$pattern = ’’; 
for($i=1; $i<=$cnt; $i++) { 

$pattern .= ’( .*=.*)’; 

//完成正则表达式形成,如/(<a)( .*=.*)( .*=.*)(>.*<\/a>/i的样式 
$pattern = "/(<$tag)$pattern(>.*<\/$tag>)/i"; 

//取得保留属性 
$replacement = match($pattern,$out[0][$key],$keep_attribute); 

//替换 
$str = str_replace($out[0][$key],$replacement,$str); 


/** 
* 说明:构造标签,保留要保留的属性 
* 参数:$reg : pattern,preg_match的表达式 
* $str : string,html字串 
* $arr : array,要保留的属性 
* 返回: 
* 返回经保留处理后的标签,如 
* <A href=’http://www。e.com’ target=_blank alt=e e e>e。com</A> 
*/ 
function match($reg,&$str,$arr) { 

//match 
preg_match($reg,$str,$out); 

//取出保留的属性 
$keep_attribute = ’’; 
foreach($arr as $k1=>$v1) { 
//定义的要保留的属性的数组 
foreach($out as $k2=>$v2) { 
//匹配=后的数组 
$attribute = trim(substr($v2,0,strpos($v2,’=’))); 
//=前面的 
if($v1 == $attribute) { 
//要保留的属性和匹配的值的=前的部分相同 
$keep_attribute .= $v2; 
//保存此匹配部分的值 


//构造返回值,结构如:<a href=xxx target=xxx class="xxx">aadd</a> 
$keep_attribute = $out[1].$keep_attribute.($out[count($out)-1]); 
//返回值 
Return $keep_attribute; 

/** 
* 显示字串内容 
*/ 
function show($str,$title=’’,$debug = True) { 

if($debug) { 
if(is_array($str)) { 
$str = print_r($str,True); 

$txtRows = count(explode("\n",$str))+1; 
echo($title.’:<br><TEXTAREA NAME="txt" ROWS="’.$txtRows.’" COLS="130">’.$str.’</TEXTAREA><br><br>’); 


?>

posted @ 2011-03-15 00:17  buffer的blogs  阅读(359)  评论(0编辑  收藏  举报