Php 保护所见即所得编辑器——HTMLPurifier真的是唯一的出路吗?

Php 保护所见即所得编辑器——HTMLPurifier真的是唯一的出路吗?,php,xss,wysiwyg,strip-tags,Php,Xss,Wysiwyg,Strip Tags,我有一个评论表,目前是纯文本。这很好,也很简单,因为我可以使用strip_标记和htmlspecialchars从中去除任何模糊的类似HTML的内容 但是,有计划将其转换为支持多个标记的HTML表单 我看到的问题是,即使去掉输入的标签并只保留这些标签,我仍然可以在标签中看到XSS和jscript 我知道HTML净化器可以用来解决这个问题,但它看起来非常笨重、缓慢,我很难相信没有更好的方法 我曾考虑改用BBCode编辑器,但假设这些代码以BB的形式插入数据库,那么我如何将其从BB转换回HTML以显

我有一个评论表,目前是纯文本。这很好,也很简单,因为我可以使用strip_标记和htmlspecialchars从中去除任何模糊的类似HTML的内容

但是,有计划将其转换为支持多个标记的HTML表单

我看到的问题是,即使去掉输入的标签并只保留这些标签,我仍然可以在标签中看到XSS和jscript

我知道HTML净化器可以用来解决这个问题,但它看起来非常笨重、缓慢,我很难相信没有更好的方法


我曾考虑改用BBCode编辑器,但假设这些代码以BB的形式插入数据库,那么我如何将其从BB转换回HTML以显示它呢?

BBCode对于您的问题来说确实是一个非常简单和有用的解决方案

我正在使用,但你肯定可以找到许多其他的

然后如何将它从BB转换回HTML以显示它

答案很简单:您可以使用
preg\u replace

我自己实现了这个,所以我可以让您使用我的解析器代码。它转换基本标记,以及一些自定义标记,如
[center]
。添加您自己的标签或替换当前标签非常容易

该脚本由一个包含正则表达式和替换的巨大数组以及一个
preg\u replace
调用组成

function replaceBBcode($str) {
    $replace = array(

        // inline text formats
        '/\[b\](.*?)\[\/b\]/is'                         => '<b>$1</b>',
        '/\[i\](.*?)\[\/i\]/is'                         => '<i>$1</i>',
        '/\[u\](.*?)\[\/u\]/is'                         => '<u>$1</u>',
        '/\[s\](.*?)\[\/s\]/is'                         => '<s>$1</s>',
        '/\[sup\](.*?)\[\/sup\]/is'                     => '<sup>$1</sup>',
        '/\[sub\](.*?)\[\/sub\]/is'                     => '<sub>$1</sub>',

        // headings
        '/\[h1\](.*?)\[\/h1\]/is'                       => '<h1>$1</h1>',
        '/\[h2\](.*?)\[\/h2\]/is'                       => '<h2>$1</h2>',
        '/\[h3\](.*?)\[\/h3\]/is'                       => '<h3>$1</h3>',
        '/\[h4\](.*?)\[\/h4\]/is'                       => '<h4>$1</h4>',
        '/\[h5\](.*?)\[\/h5\]/is'                       => '<h5>$1</h5>',

        // formatting tags
        '/\[(?:hr|line)\]/is'                           => '<hr />',
        '/\[br\/?\]/is'                                 => '<br />',

        // links
        '/\[url=([^\]]+)\](.*?)\[\/url\]/is'            => '<a href="$1">$2</a>',
        '/\[link=([^\]]+)\](.*?)\[\/link\]/is'          => '<a href="$1">$2</a>',
        '/\[url\](.*?)\[\/url\]/is'                     => '<a href="$1" title="$1">$1</a>',
        '/\[link\](.*?)\[\/link\]/is'                   => '<a href="$1" title="$1">$1</a>',

        '/\[img=([^\]]+)\]/is'                          => '<img src="$1" alt="" />',

        // text blocks and block formats
        '/\[font=([^\]]+)\](.*?)\[\/font\]/is'          => '<span style="font-family: $1;">$2</span>',
        '/\[size=([0-9]+)\](.*?)\[\/size\]/is'          => '<span style="font-size: $1pt;">$2</span>',
        '/\[color=([^\]]+)\](.*?)\[\/color\]/is'        => '<span style="color: $1;">$2</span>',
        '/\[bgcolor=([^\]]+)\](.*?)\[\/bgcolor\]/is'    => '<span style="background-color: $1;">$2</span>',
        '/\[p\](.*?)\[\/p\]/is'                         => '<p>$1</p>',

        // alignment blocks
        '/\[align=(left|center|right|justify)\](.*?)\[\/align\]/is'     => '<div style="text-align: $1;">$2</div>',
        '/\[center\](.*?)\[\/center\]/is'               => '<div style="text-align: center;">$1</div>',
        '/\[left\](.*?)\[\/left\]/is'                   => '<div style="text-align: left;">$1</div>',
        '/\[right\](.*?)\[\/right\]/is'                 => '<div style="text-align: right;">$1</div>',
        '/\[justify\](.*?)\[\/justify\]/is'             => '<div style="text-align: justify;">$1</div>',

        // lists
        '/\[list=(disc|circle|square)\](.*?)\[\/list\]/is'  => '<ul style="list-style-type:$1;">$2</ul>',
        '/\[list\](.*?)\[\/list\]/is'                   => '<ul>$1</ul>',
        '/\[list=a\](.*?)\[\/list\]/s'                  => '<ol style="list-style-type:lower-alpha;">$1</ol>',
        '/\[LIST=a\](.*?)\[\/LIST\]/s'                  => '<ol style="list-style-type:lower-alpha;">$1</ol>',
        '/\[list=A\](.*?)\[\/list\]/s'                  => '<ol style="list-style-type:upper-alpha;">$1</ol>',
        '/\[LIST=A\](.*?)\[\/LIST\]/s'                  => '<ol style="list-style-type:upper-alpha;">$1</ol>',
        '/\[list=1\](.*?)\[\/list\]/is'                 => '<ol style="list-style-type:decimal;">$1</ol>',
        '/\[list=I\](.*?)\[\/list\]/is'                 => '<ol style="list-style-type:upper-roman;">$1</ol>',
        '/\[\*\]/is'                                    => '<li>',

        // videos
        '/\[(?:youtube|video|media|movie){1}\](?:https?\:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtube\.com\/v\/|youtu\.be\/)?([a-z0-9\-\_]+)\[\/(?:youtube|video|media|movie){1}\]/is'
                    => '<iframe width="560" height="315" src="http://www.youtube.com/embed/$1?wmode=opaque" frameborder="0" allowfullscreen></iframe>',
    );

    // do the tags
    $str = preg_replace (array_keys($replace), array_values($replace), $str);  

    return $str; 
}

如果您有时间和精力编写自己的验证方案,请考虑另一个时间,因为这很复杂。

首先,看看如果不使用递归会发生什么

坏话:复制这个

CopyCopyThisThis
这就给你留下了

CopyThis

坏词…

为什么不使用简单的BBcode解析器?HTML净化器有什么问题?速度不太可能是一个实际问题。而且它体积庞大,因为清理HTML id是一件复杂的事情。不过,这是否能防止XSS漏洞,而XSS漏洞正是OPs最关心的问题?我看起来不像。如果我做了什么;[\/right\]?当然,您应该首先通过strip\u标记发送输入,然后再将其保存到数据库中。这段代码只是渲染部分。啊,我明白了。因此,您可以使用BBCode作为输入语言,而不是HTML。很好,是的。现在我还编辑了这个帖子,包括一些安全性的东西,正如你所指出的。这是为了强调一些典型的问题,很多人在清理或摘除标签/属性等时不考虑。
CopyThis