Laravel-转义除<img>和<br>标记外的所有HTML字符

时间:2019-10-24 21:08:54

标签: php laravel security xss

我正在创建一个论坛,我只希望在该论坛上显示img标签,并希望所有其他标签安全地转义, 但不 被删除。除了从头开始创建函数之外,完成此任务的最佳方法是什么?

我尝试使用HTML Purifier,但它会剥离所有不需要的标签,而仅保留所需的标签。此外,我尝试了其他功能,例如strip_tags和htmlentities以及blaede({{ }})中使用的转义运算符,但这些功能将剥离不需要的标签(我希望将其转义)或转义所有标签(我也不想要,因为我想保留<img><br>标签。我看到了其他类似的问题,但不幸的是,它们都没有真正帮助过我。

到目前为止,我正在使用的是: $post->content = Purifier::clean($request->content); 暂时删除不需要的标签以防止XSS。

我希望用户插入的数据显示如下:

Hi all
<script>alert('hi all')</script>
<img src='sun.png'/>

现在显示以下内容

Hi all
 hi all 
<img src='sun.png'/>

更新:

我的问题与被标记的问题重复了 。希望主持人能够解决这个问题。

1 个答案:

答案 0 :(得分:1)

您需要先用一些字符串占位符替换<img><br>标签,再用htmlentities()进行转义,然后恢复原始的<img><br>标签背部。这是解决问题的方法:

$string = "Hi<br> all<script>alert('hi all')</script><img src='sun.png'/>";

// First we cleanup our string from possible pre-existing placeholders (like $$0, $$1 etc).
$string = preg_replace('~\$\$[0-9]+~', '', $string);

// Then we replace all <img> and <br> tags with such placeholders while
// storing them into $placeholders array.
$placeholders = [];
$i = 0;
$string = preg_replace_callback('~(<img[^>]*>(</img>)?|<br[^>]*>)~', function ($matches) use (&$placeholders, &$i) {
    $key = '$$'.$i++;
    $placeholders[$key] = $matches[0];

    return $key;
}, $string);

// Our string no longer has <img> and <br> tags so we can safely escape
// the rest.
$string = htmlentities($string);

// Lastly we restore <img> and <br> tags by swapping them back instead of their respective placeholders.
foreach ($placeholders as $key => $placeholder) {
    $string = str_replace($key, $placeholder, $string);
}

echo $string;

此代码将产生结果:

Hi<br> all&lt;script&gt;alert('hi all')&lt;/script&gt;<img src='sun.png'/>

此解决方案在很大程度上依赖于使用正则表达式,因此我强烈建议您学习此主题,以防日后需要调整代码。