【问题标题】:Laravel - escape all HTML characters apart from <img> and <br> tagsLaravel - 转义除 <img> 和 <br> 标签之外的所有 HTML 字符
【发布时间】:2019-10-24 21:08:54
【问题描述】:

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

我曾尝试使用 HTML Purifier,但它会去除所有不需要的标签,只保留所需的标签。此外,我尝试了其他函数,例如 strip_tags 和 htmlentities 以及 blaede 中使用的转义运算符({{ }}),但这些函数要么剥离不需要的标签(我希望它们被转义)要么转义所有标签(我也不想这样做,因为我想保留 &lt;img&gt;&lt;br&gt; 标签。我看到了其他类似的问题,但不幸的是,它们都没有真正帮助我。

到目前为止,我所做的是使用: $post-&gt;content = Purifier::clean($request-&gt;content); 临时删除不需要的标签以防止 XSS。

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

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

现在正在显示以下内容

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

更新:

我的问题没有与被标记的问题重复。希望版主能解决这个问题。

【问题讨论】:

  • @zbee 他说他不想剥掉它们。
  • @zbee 我清楚地提到我***不***想要剥离标签。 所有其他标签被安全转义,但不被删除
  • @Samad 所有其他标签被安全转义,但不被删除

标签: php laravel security xss


【解决方案1】:

你需要先用一些字符串占位符替换&lt;img&gt;&lt;br&gt;标签,用htmlentities()进行转义,然后恢复原来的&lt;img&gt;&lt;br&gt;标签。以下是你可以做到的技巧:

$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'/>

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

【讨论】:

  • 嗨@d3jn,感谢您的回答。它适用于我,我理解你的代码。但是,我假设没有更好的方法,对吗?就我而言,我稍微更改了键,以允许用户输入像 $$1 这样很少见的东西。
  • @GeorGios 遗憾的是,我不知道 PHP 中有任何现成的解决方案可以解决您的问题。将此代码包装到一个自定义全局函数中,该函数接收参数类似于strip_tags 的做法,除了将其命名为escape_tags 或其他名称(您还可以添加代码,从传入标签的数组中生成正则表达式等)并使用它贯穿您的整个项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
相关资源
最近更新 更多