Константа FILTER_SANITIZE_STRING устарела

Я установил PHP 8.1 и начал тестировать свой старый проект. Я использовал фильтр FILTER_SANITIZE_STRING вот так:

      $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);

Теперь я получаю такую ​​ошибку:

Устарело: константа FILTER_SANITIZE_STRING устарела

То же самое происходит, когда я использую FILTER_SANITIZE_STRIPPED:

Устарело: константа FILTER_SANITIZE_STRIPPED устарела

Чем я могу его заменить?

6 ответов

Решение

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

Поведение этого фильтра было очень не интуитивно понятным. Он удалил все между < и до конца строки или до следующего >. Он также удалил все NULбайтов. Наконец, он закодировал ' а также " в свои HTML-объекты.

Если вы хотите заменить его, у вас есть несколько вариантов:

  1. Использовать строковый фильтр по умолчанию FILTER_UNSAFE_RAWэто не выполняет никакой фильтрации. Это следует использовать, если вы не имели представления о поведении FILTER_SANITIZE_STRING и вы просто хотите использовать фильтр по умолчанию, который даст вам строковое значение.

  2. Если вы использовали этот фильтр для защиты от XSS-уязвимостей, замените его использование на htmlspecialchars(). Не вызывайте эту функцию для входных данных. Для защиты от XSS вам нужно закодировать вывод!

  3. Если вы точно знали, что делает этот фильтр, и хотите создать полифилл, вы можете легко сделать это с помощью регулярного выражения.

            function filter_string_polyfill(string $string): string
    {
        $str = preg_replace('/\x00|<[^>]*>?/', '', $string);
        return str_replace(["'", '"'], ['&#39;', '&#34;'], $str);
    }
    

Ближайшая константа, которую вы можете использовать вместо этого, если вы собираетесь преобразовать свою переменную в безопасную строку html, это FILTER_SANITIZE_FULL_SPECIAL_CHARS.

Из документации вы должны заменить его наhtmlspecialchars().

FILTER_SANITIZE_STRING

Удалите теги и HTML-кодируйте двойные и одинарные кавычки, при необходимости удалите или закодируйте специальные символы. Кодирование кавычек можно отключить, установив FILTER_FLAG_NO_ENCODE_QUOTES. (Устарело с PHP 8.1.0, вместо этого используйте htmlspecialchars().)

FILTER_SANITIZE_STRIPPED

Псевдоним фильтра "string". (Устарело с PHP 8.1.0, вместо этого используйте htmlspecialchars().)

Вот как я заменил константу FILTER_SANITIZE_STRING. Таким образом вы также можете использовать флаги.

У меня было несколько серверных тестов PHP, и они отлично работают с этим методом. Улучшения приветствуются.

      /**
 * @param string $value
 * @param array $flags
 * @return string
 */
private static function sanitizeFilterString($value, array $flags): string
{
    $noQuotes = in_array(FILTER_FLAG_NO_ENCODE_QUOTES, $flags);
    $options = ($noQuotes ? ENT_NOQUOTES : ENT_QUOTES) | ENT_SUBSTITUTE;
    $optionsDecode = ($noQuotes ? ENT_QUOTES : ENT_NOQUOTES) | ENT_SUBSTITUTE;

    // Strip the tags
    $value = strip_tags($value);

    // Run the replacement for FILTER_SANITIZE_STRING
    $value = htmlspecialchars($value, $options);

    // Fix that HTML entities are converted to entity numbers instead of entity name (e.g. ' -> &#34; and not ' -> &quote;)
    // https://stackoverflow.com/questions/64083440/use-php-htmlentities-to-convert-special-characters-to-their-entity-number-rather
    $value = str_replace(["&quot;", "&#039;"], ["&#34;", "&#39;"], $value);

    // Decode all entities
    return html_entity_decode($value, $optionsDecode);
}

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

Даже если в результате какого-либо изменения код JS попадает в базу данных, его содержимое искажается, поскольку кавычки, одинарные кавычки и < > преобразуются в эквивалент HTML. Если мы повторим содержимое поля как есть, пользователь все равно будет в безопасности, потому что тег искажен таким образом, что он не будет работать. Конечно, мы можем ошибаться, но с проблемами, непосредственно связанными с фильтром, мы не сталкивались.

Есть некоторые клавиатуры, которые не имеют надлежащего языка клавиатуры, поэтому кавычки, которые они вводят в поля, могут привести или не привести к фигурным кавычкам, что является проклятием для чтения этой строки в поле ввода.

Кто-то может возразить, что вывод этой конкретной строки должен быть экранирован, но зачем тратить две дополнительные строки кода на экранирование вывода для N разных выходов, когда можно просто очистить строку перед вводом данных в базу данных?

Мы никогда не слышали, чтобы FILTER_SANITIZE_STRING преследовал цель предотвращения XSS, поскольку мы не совсем используем фильтр для этой конкретной задачи.

В ссылке «Не пытайтесь дезинфицировать» нет упоминания об использовании FILTER_SANITIZE_STRING.

Нам дают пример (который я немного модифицировал):

      $name ="Robert'); DROP TABLE users;";
$query = "SELECT * FROM users WHERE name = '{$name}'";
echo $query;

Это дает:

SELECT * FROM users WHERE name = 'Robert'); DROP TABLE пользователей

как и ожидалось, это SQL-инъекция.

Но если мы отфильтруем это:

      $name = filter_var("Robert'); DROP TABLE users",FILTER_SANITIZE_STRING);
$query = "SELECT * FROM users WHERE name = '{$name}'";
echo $query;

Это дает:

SELECT * FROM users WHERE name = 'Robert'); DROP TABLE пользователей

Мы закончим запрашивать имя пользователя под названием «Роберт &#39;); DROP TABLE users", и запрос не даст результатов.

Мы надеемся, что сопровождающие PHP придут к нам, увидят полезность фильтра и сохранят его. Но если нет, то нам просто придется использовать полифилл

Его можно легко заменить на это:

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