Удалить теги в PHP со списком разрешенных, но удалить все атрибуты

В PHP это самый быстрый и простой способ удалить все теги HTML из строки, кроме тех, которые находятся в разрешенном списке, но путем удаления всех атрибутов HTML.

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

Очень хакерское, но простое решение — заменить теги, которые вы хотите сохранить, замещающим символом или строкой, а затем вызвать strip_tags. После этого замените разрешенные теги обратно. Но из соображений безопасности я бы вообще не использовал strip_tags, если только ввод не проверен иным образом.

Ood 22.03.2024 00:36

Извините, но я не могу понять решение, которое вы предложили. Разве это не было бы так же, как если бы я просто использовал strip_tags с разрешенными тегами? Также не могли бы вы объяснить, почему вы не используете strip_tags из соображений безопасности?

Klax Cuy 22.03.2024 00:47

В коде WordPress имеется проверенный в боевых условиях очиститель HTML FWIW. Developer.wordpress.org/reference/functions/wp_kses

O. Jones 22.03.2024 01:08

В этом вопросе отсутствует минимальный воспроизводимый пример и попытка кодирования.

mickmackusa 22.03.2024 02:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
4
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Регулярное выражение может привести к сбою, если атрибут имеет > в качестве значения атрибута.

Более безопасным способом было бы использовать DomDocumment, но учтите, что входные данные должны быть действительными HTML, а выходные данные могут быть стандартизированы.

<?php

$htmlString = '<span>777</span><div class = "hello">hello <b id = "12">world</b></div>';
$stripped = strip_tags($htmlString, '<div><b>');

$dom = new DOMDocument;              // init new DOMDocument
$dom->loadHTML($stripped);           // load the HTML
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//@*');
foreach ($nodes as $node) {
    $node->parentNode->removeAttribute($node->nodeName);
}

$cleanHtmlString = '';
foreach ($dom->documentElement->firstChild->childNodes as $node) {
    $cleanHtmlString .= $dom->saveHTML($node);
}

echo $cleanHtmlString;

Выход:

<p>777</p>
<div>hello <b>world</b>
</div>

Я собирался написать аналогичное решение, но стоит ли мне беспокоиться о стоимости производительности? Если, например, анализируется несколько строк HTML различной длины, будет ли это тем или иным образом наказываться?

Klax Cuy 22.03.2024 01:12

Я думаю, что буду использовать это решение с системой кэширования.

Klax Cuy 22.03.2024 01:30

Прежде всего, strip_tags не предотвращает XXS-атаки, поэтому с точки зрения безопасности я бы не рекомендовал его, см. здесь.

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

$string = '<b class = "hello">Hello, </b><a>world!</a>';

$allowed = array(

    'b' => chr(1) . 'b_open',
    '/b' => chr(1) . 'b_close',
    'i' => chr(1) . 'i_open',
    '/i' => chr(1) . 'i_close',

);

// Remove your special character from the input to prevent it from being injected

$result = str_replace(chr(1), '', $string);

// Escape the valid tags

foreach ($allowed as $tag => $replacement) {

    $result = preg_replace('/<' . str_replace('/', '\/', $tag) . '([^>]*?)>/i', $replacement, $result);

}

// Call strip_tags

$result = strip_tags($result);

// Replace back

foreach ($allowed as $tag => $replacement) {

    $result = str_replace($replacement, '<' . $tag . '>', $result);

}

echo($result);

Спасибо за разъяснения, но, по моему мнению, strip_tags не предотвращает XSS-атаки, только если вы используете второй параметр, поскольку, как я уже говорил в своем вопросе, он не удалит атрибуты из разрешенного списка, что и является сутью моего вопроса. . И еще раз извините, но я не совсем понимаю цель того, что вы предложили. Кроме того, предоставленный вами код не обрабатывает атрибуты HTML. Так что же мне не хватает?

Klax Cuy 22.03.2024 01:18

@KlaxCuy Если функциональность атрибута важна, я добавил это. Но, как было указано, в некоторых случаях регулярное выражение может дать сбой. Это возможное решение, в котором специально используется strip_tags с меньшей сложностью.

Ood 22.03.2024 01:55

Другие вопросы по теме