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

4257次阅读  |  发布于5年以前

继上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

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8