我已经安装了 PHP 8.1,并开始测试我的旧项目。我已经使用了过滤器
FILTER_SANITIZE_STRING
,如下所示:
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
现在我收到此错误:
已弃用:常量 FILTER_SANITIZE_STRING 已弃用
当我使用
FILTER_SANITIZE_STRIPPED
时也会发生同样的情况:
已弃用:常量 FILTER_SANITIZE_STRIPPED 已弃用
我可以用什么来代替它?
这个过滤器的用途不明确。很难说它到底要实现什么目的或何时应该使用它。由于其名称,它也与默认字符串过滤器混淆,而实际上默认字符串过滤器称为
FILTER_UNSAFE_RAW
。 PHP 社区决定不再支持使用此过滤器。
这个过滤器的行为非常不直观。它删除了
<
和字符串末尾之间或直到下一个 >
之前的所有内容。它还删除了所有 NUL
字节。最后,它将 '
和 "
编码到它们的 HTML 实体中。
如果您想更换它,您有几个选择:
使用不执行任何过滤的默认字符串过滤器
FILTER_UNSAFE_RAW
。如果您不知道 FILTER_SANITIZE_STRING
的行为并且只想使用默认过滤器来提供字符串值,则应该使用此方法。
htmlspecialchars()
。不要对输入数据调用此函数。为了防止 XSS,您需要对输出进行编码!
如果您确切知道该过滤器的作用并且想要创建一个polyfill,则可以使用正则表达式轻松完成。
function filter_string_polyfill(string $string): string
{
$str = preg_replace('/\x00|<[^>]*>?/', '', $string);
return str_replace(["'", '"'], [''', '"'], $str);
}
如果您打算将变量转换为安全的 html 字符串,则可以使用的最接近的常量是 FILTER_SANITIZE_FULL_SPECIAL_CHARS
从文档中,您应该将其替换为
htmlspecialchars()
。
FILTER_SANITIZE_STRING
剥离标签并对双引号和单引号进行 HTML 编码,可选择剥离或编码特殊字符。可以通过设置 FILTER_FLAG_NO_ENCODE_QUOTES 来禁用引号编码。 (从 PHP 8.1.0 开始已弃用,请使用 htmlspecialchars() 代替。)
过滤器消毒_剥离
“字符串”过滤器的别名。 (从 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. ' -> " and not ' -> "e;)
// https://stackoverflow.com/questions/64083440/use-php-htmlentities-to-convert-special-characters-to-their-entity-number-rather
$value = str_replace([""", "'"], [""", "'"], $value);
// Decode all entities
return html_entity_decode($value, $optionsDecode);
}
与这个问题相关的是使用
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(["'", '"'], [''', '"'], $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
版本约为。快两倍。
可以很容易地用这个替换:
FILTER_UNSAFE_RAW