用PHP中的htmlspecialchars()替换除了某些html标签以外的所有标签?

时间:2014-08-09 21:36:49

标签: php html html-entities htmlspecialchars strip-tags

我想处理我的用户输入以仅允许某些html标记,并用其html实体替换其他标记,以及替换非标记字符。例如,如果我只想允许<b><a>标记,那么

allow_only("This is <b>bold</b> and this is <i>italic</i>.
            Moreover 2<3 and <a href='google.com'>this is a link</a>.","<b><a>");

应该产生

This is <b>bold</b> and this is &lt;i&gt;italic&lt;/i&gt;.
Moreover 2&lt;3 and <a href='google.com'>this is a link</a>.

我怎样才能在PHP中执行此操作?我知道strip_tags()可以完全删除不需要的代码,并且我知道htmlspecialchars()可以替换所有代码他们的html实体,但没有特定标签被替换。如何在PHP中完成?

如果没有共同的&#39;如何做到这一点,我应该如何继续处理可以有有效的常规html的用户输入,但也可以有<标志和潜在危险的HTML代码?

1 个答案:

答案 0 :(得分:2)

应用htmlspecialchars,然后将编码实体替换为给定标记数组的常规实体

function allow_only($str, $allowed){
    $str = htmlspecialchars($str);
    foreach( $allowed as $a ){
        $str = str_replace("&lt;".$a."&gt;", "<".$a.">", $str);
        $str = str_replace("&lt;/".$a."&gt;", "</".$a.">", $str);
    }
    return $str;
}
echo allow_only("This is <b>bold</b> and this is <i>italic</i>.", array("b"));

适用于简单标签,返回&#34;这是粗体,这是&lt; i&gt; italic&lt; / i&gt;。&#34;

正如有人指出的那样,对于带有属性的标签不起作用,但这样做:

function fix_attributes($match){
    return "<".$match[1].str_replace('&quot;','"',$match[2]).">";
}
function allow_only($str, $allowed){
    $str = htmlspecialchars($str);
    foreach( $allowed as $a ){
        $str = preg_replace_callback("/&lt;(".$a."){1}([\s\/\.\w=&;:#]*?)&gt;/", fix_attributes, $str);
        $str = str_replace("&lt;/".$a."&gt;", "</".$a.">", $str);
    }
    return $str;
}
echo allow_only('This is <b>bold</b> and <a href="http://www.#links">this</a> is <i>italic</i>.', array("b","a"));

处理具有特定属性的更复杂的标记,只允许[]之间列出的字符出现在属性中。遗憾的是,&quot;必须在属性中被允许,或者它不会起作用,并且允许所有其他实体也被允许 - 但是属性中只有&quot将被解码。

因为建议使用像http://htmlpurifier.org/demo.php这样的库来更好(更安全,更清洁)解决这类问题的方法