常量 FILTER_SANITIZE_STRING 已弃用

问题描述 投票:0回答:6

我已经安装了 PHP 8.1,并开始测试我的旧项目。我已经使用了过滤器

FILTER_SANITIZE_STRING
,如下所示:

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

现在我收到此错误:

已弃用:常量 FILTER_SANITIZE_STRING 已弃用

当我使用

FILTER_SANITIZE_STRIPPED
时也会发生同样的情况:

已弃用:常量 FILTER_SANITIZE_STRIPPED 已弃用

我可以用什么来代替它?

php filter sanitization php-8.1
6个回答
86
投票

这个过滤器的用途不明确。很难说它到底要实现什么目的或何时应该使用它。由于其名称,它也与默认字符串过滤器混淆,而实际上默认字符串过滤器称为

FILTER_UNSAFE_RAW
。 PHP 社区决定不再支持使用此过滤器。

这个过滤器的行为非常不直观。它删除了

<
和字符串末尾之间或直到下一个
>
之前的所有内容。它还删除了所有
NUL
字节。最后,它将
'
"
编码到它们的 HTML 实体中。

如果您想更换它,您有几个选择:

  1. 使用不执行任何过滤的默认字符串过滤器

    FILTER_UNSAFE_RAW
    。如果您不知道
    FILTER_SANITIZE_STRING
    的行为并且只想使用默认过滤器来提供字符串值,则应该使用此方法。

  2. 如果您使用此过滤器来防御 XSS 漏洞,请将其用法替换为

    htmlspecialchars()
    。不要对输入数据调用此函数。为了防止 XSS,您需要对输出进行编码!

  3. 如果您确切知道该过滤器的作用并且想要创建一个polyfill,则可以使用正则表达式轻松完成。

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

不要尝试清理输入。转义输出。


55
投票

如果您打算将变量转换为安全的 html 字符串,则可以使用的最接近的常量是 FILTER_SANITIZE_FULL_SPECIAL_CHARS


11
投票

文档中,您应该将其替换为

htmlspecialchars()

FILTER_SANITIZE_STRING

剥离标签并对双引号和单引号进行 HTML 编码,可选择剥离或编码特殊字符。可以通过设置 FILTER_FLAG_NO_ENCODE_QUOTES 来禁用引号编码。 (从 PHP 8.1.0 开始已弃用,请使用 htmlspecialchars() 代替。)

过滤器消毒_剥离

“字符串”过滤器的别名。 (从 PHP 8.1.0 开始已弃用,请使用 htmlspecialchars() 代替。)


0
投票

这就是我替换 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);
}

0
投票

与这个问题相关的是使用

filter_input_array
FILTER_SANITIZE_STRING
来一次“清理”$_POST中的所有元素

$_POST  = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);

按照 Dharman 的建议,

FILTER_SANITIZE_STRING
的行为可以通过这个 polyfill 函数复制:

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

现在出现的问题是如何立即将这个函数全局应用到所有 $_POST 元素上。不幸的是,将

filter_input_array
FILTER_CALLBACK
结合使用失败了。

但是,我发现以下解决方案会生成与上面的表达式等效的输出

foreach ($_POST as $key => $value) {
    $_POST[$key] = filter_var($value, FILTER_CALLBACK, ['options' => 'filter_string_polyfill']);
}

通过这种方式,$_POST 对所有元素都进行了“清理”,而无需使用现已弃用的

FILTER_SANITIZE_STRING

关于效率,我使用

microtime()
测量了两个版本的时间跨度。正如预期的那样,
filter_input_array
版本约为。快两倍。


-9
投票

可以很容易地用这个替换:

FILTER_UNSAFE_RAW
© www.soinside.com 2019 - 2024. All rights reserved.