17

这是我拥有的代码行,效果很好:

$content = htmlspecialchars($_POST['content'], ENT_QUOTES);

但我想做的是只允许某些类型的 HTML 代码通过而不被转换。这是我希望通过的 HTML 代码列表:

<pre> </pre>
<b> </b>
<em> </em>
<u> </u>
<ul> </ul>
<li> </li>
<ol> </ol>

在我进行的过程中,我还希望能够在以后添加更多的 HTML,因为我想到了它。有人可以帮我修改上面的代码,以便上面指定的 HTML 代码列表可以通过而不被转换吗?

4

6 回答 6

14

我想你可以在事后做到这一点:

// $str is the result of htmlspecialchars()
preg_replace('#&lt;(/?(?:pre|b|em|u|ul|li|ol))&gt;#', '<\1>', $str);

它允许在一组受控的允许标签中的编码版本<xx></xx>位置。xx

于 2012-10-10T12:57:39.543 回答
6

或者您可以使用旧样式:

$content = htmlspecialchars($_POST['content'], ENT_QUOTES);

$turned = array( '&lt;pre&gt;', '&lt;/pre&gt;', '&lt;b&gt;', '&lt;/b&gt;', '&lt;em&gt;', '&lt;/em&gt;', '&lt;u&gt;', '&lt;/u&gt;', '&lt;ul&gt;', '&lt;/ul&gt;', '&lt;li&gt;', '&lt;/li&gt;', '&lt;ol&gt;', '&lt;/ol&gt;' );
$turn_back = array( '<pre>', '</pre>', '<b>', '</b>', '<em>', '</em>', '<u>', '</u>', '<ul>', '</ul>', '<li>', '</li>', '<ol>', '</ol>' );

$content = str_replace( $turned, $turn_back, $content );
于 2012-10-10T12:59:34.143 回答
2

我改进了杰克攻击这个问题的方式。我添加了对<br>, <br/>和锚标签的支持。代码将替换 fisthref=&quot;...&quot;以仅允许使用此属性。

$str = preg_replace(
    array('#href=&quot;(.*)&quot;#', '#&lt;(/?(?:pre|a|b|br|em|u|ul|li|ol)(\shref=".*")?/?)&gt;#' ), 
    array( 'href="\1"', '<\1>' ), 
    $str
);
于 2015-02-13T17:24:49.497 回答
1

我制作了这个函数来清理除指定的 HTML 标记之外的所有 HTML 特殊字符。

它首先使用 htmlspecialchars() 使字符串安全,然后恢复我想要不受影响的标签。

该功能支持属性过滤作为选项,但是如果您关心可能的 XSS 攻击,请小心禁用它。

我知道正则表达式效率不高,但对于中等长度的字符串应该没问题。您可以检查我在这里使用的正则表达式 https://regex101.com/r/U6GQse/8

public function sanitizeHtml($string, $safeHtmlTags = array('b','i','u','br'), $filterAttributes = true)
{
    $string = htmlspecialchars($string);

    if ($filterAttributes) {
        $replace = "<$1$2$4>";
    } else {
        $replace = "<$1$2$3$4>";
    }
    $string = preg_replace("/&lt;\s*(\/?\s*)(".implode("|", $safeHtmlTags).")(\s?|\s+[\s\S]*?)(\/)?\s*&gt;/", $replace, $string);

    return $string;
}

// Example usage to answer the OP question
$str = "MY HTML CONTENT"
echo sanitizeHtml($str, array('pre','b','em','u','ul','li','ol'));
于 2019-12-17T15:18:15.117 回答
0

我喜欢 Elwin 的解决方案,但您可能想要:

  1. 防止 Javascript:URL 位于href- 或更可能:仅允许http(s).
  2. 如果内容中有多个<a href>',则使正则表达式 glob 不贪婪。

这是更新的版本:

$str = preg_replace(
    array('#href=&quot;(https?://.*?)&quot;#', '#&lt;(/?(?:pre|a|b|br|em|u|ul|li|ol)(\shref=".*?")?/?)&gt;#' ), 
    array( 'href="\1"', '<\1>' ), 
    $str
);
于 2019-12-11T10:17:57.503 回答
-3

你可以使用 strip_tags

$exceptionString = '<pre>,</pre>,<b>,</b>,<em>,</em>,<u>,</u>,<ul>,</ul>,<li>,</li>,<ol>,</ol>';

$content = strip_tags($_POST['content'],$exceptionString );
于 2012-10-10T13:02:03.950 回答