03月05, 2012

500行PHP代码搞定富文本安全过滤

继上2篇文章讲到利用JSON这种格式化的数据进行传输,后端只要差不多500行左右的PHP代码就搞定了整个富文本安全过滤。由于每个编辑器支持的功能不同,所以对应的后端过滤策略也不同。本文详细介绍下如果通过配置使用json2html达到你所需要的过滤效果。

由于安全漏洞是无穷无尽的,所以使用黑名单的方式肯定不能杜绝所有的安全漏洞。json2html完全是利用白名单的方式,一切不在白名单之类的内容都将会被过滤掉,从而保证过滤后的数据是安全的。

使用方法

require_once '../src/json2html.class.php';
 $json = "json content";
 $instance = new JSON2HTML($json, $options);
//$instance->xxx 设置各种白名单 
//获取过滤后的结果
$result = $instance->run();

配置选项$options

public $options = array (
 "checkTag" => true, //是否检测tag
 "checkAttr" => true, //是否检测属性名
 "filterAttrValue" => true, //是否过滤属性值
 "escapeHtml" => true, //是否进行html转码
 "tagAttrRequired" => true, //标签必须包含的属性
 "tagChildRequired" => true, //标签必须包含的子元素
 );

过滤规则和接口

1、标签白名单

默认配置白名单:

public $tagBlankList = array (
 "a", "span", "img", "p", "br",
 "div", "strong", "b", "ul", "li", "ol", "embed","object","param", "u"
 );

可以通过下面的方法添加和移除标签白名单:

$instance->addTagBlank($tag); //$tag可以是单个标签名,也可以是多个标签名组成的数组
$instance->addTagBlank("em"); //增加em标签
$instance->addTagBlank(array("em", "pre", "h1")); //增加em,pre,h1标签
$instance->removeTagBlank("em");// 移除em标签
$instance->removeTagBlank(array("em", "pre")); //移除em,pre标签

2、标签属性名白名单

默认配置白名单:

public $attrBlankList = array (
 "*" => array ("id", "class", "name", "style", "value" ),
 "a" => array ("href", "title" ),
 "img" => array ("width", "src", "height", "alt" ),
 "embed" => array("width", "height", "allowscriptaccess", "type", "src"),
 "param" => array("allowscriptaccess"),
 );

可以通过下面的方法添加和移除标签属性白名单:

$instance->addAttrBlank($attr, $tag); //$attr可以是字符串或者数组
$instance->addAttrBlank("title", "*"); //给所有的标签加上title属性
$instance->addAttrBlank("_target", "a"); //给a标签增加_target属性
$instance->addAttrBlank(array("_target", "rel"), "a"); //给a标签增加_target和rel属性
$instance->removeAttrBlank("_target"); //移除所有标签的_target属性

3、标签属性值每个过滤规则

由于每个标签属性值过滤规则可能都不一样,所以是通过方法的方式进行,如:

protected function _filterSrcAttrValue($value = '', $tag = ''); //src值的过滤规则
protected function _filterHrefAttrValue($value = '', $tag = '') ; //href值的过滤规则
protected function _filterStyleAttrValue($value = '', $tag = '') ; //style值的过滤规则

如果需要扩展的话,可以通过一个类继承json2html类来实现,如:

class myEdito extends json2html{
    protected function _fitlerTitleAttrValue($value, $tag) //过滤title规则
}

4、标签里必须含有某些属性和值规则

有些标签必须含有某些属性,并且属性值是我们给定的,系统默认属性如下:

public $tagAttrRequired = array (
 "embed" => array (
 "allowscriptaccess" => "never",
 "type" => "application/x-shockwave-flash"
 ),
 );

表示embed标签含有allowscriptaccess和type属性,并且值也是我们给定的,如果要过滤的JSON文本里含有这样的属性,也会被我们给定的值覆盖。

可以通过下面的方法增加或移除标签必须含有的属性和值:

$instance->addTagAttrRequired($attrs = array(), $tag);
$instance->removeTagAttrRequired($attrs = array(), $tag);

5、标签包含的子标签必须包含某些属性和值规则

相对于有些标签必须含有某些属性和值,有些标签必须含有特定的子标签,并且子标签必须含有某些属性和值,如:object标签

系统默认配置如下:

public $tagChildRequired = array(
 "object" => array(
 /**
 * object里必须包含param,并且是指定的属性,如果有这个子标签但属性值不一致,则覆盖掉
 */
 "param" => array(
 array("where" => array("name" => "allowscriptaccess"), "value"=> array("value" => "never")),
 )
 )
 );

表示object标签必须含有param标签,并且查询到name="allowscriptaccess"里,并且有value="never"。

6、style属性值检测规则

style属性值对应的css文本需要进行过滤,系统默认配置如下:

public $styleValueBlankList = array (
 'font-family' => "/^(.){2,20}$/",
 'font-size' => "/^\d+[a-z]{2,5}$/",
 "color" => "/^(rgb\s*\(\d+\s*,\s*\d+\s*,\s*\d+\))|(\#[0-9a-f]{6})$/",
 "text-align" => array("left", "right", "center"),
 "background-color" => "/^(rgb\s*\(\d+\s*,\s*\d+\s*,\s*\d+\))|(\#[0-9a-f]{6})$/",
 );

可以通过下面的方法添加或者移除style属性值检测规则:

$instance->addStyleValueBlank($cssAttr, $value); //$value可以是正则,也可以是数组。
$instance->removeStyleValueBlank($cssAttr);

以上就是所有json2html的配置选项了,你可以通过配置选项打造你自己的富文本过滤规则。

项目地址:https://github.com/welefen/html2json

本文链接:http://welefen.com/post/only-500-line-php-code-for-filter-rich-content.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。