Laravel - экранируйте все символы HTML, кроме тегов <img>и <br> - PullRequest
0 голосов
/ 25 октября 2019

Я создаю форум, на котором я хочу, чтобы отображались только теги img, а все остальные теги были надежно экранированы, , но не удалены. Каков наилучший метод для решения этой задачи, кроме создания функции с нуля?

Я пытался использовать HTML Purifier, но он удаляет все нежелательные теги и сохраняет только нужные. Кроме того, я пробовал другие функции, такие как strip_tags и htmlentities, а также оператор escape, используемый в блейде ({{ }}), но эти функции будут либо удалять ненужные теги (которые я хочу вместо них экранировать), либо экранировать все теги. (что я тоже не хочу, потому что я хочу сохранить теги <img> и <br>. Я видел другие похожие заданные вопросы, но, к сожалению, ни один из них мне не помог.

Пока что яdo использует: $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 Ответ

1 голос
/ 25 октября 2019

Сначала необходимо заменить теги <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'/>

Это решение в значительной степени основано на использовании регулярных выражений, поэтому я настоятельно советую вам изучить этотТема на случай, если позже вам понадобится настроить код.

...