常量FILTER_SANITIZE_STRING已弃用。

77

我已安装了PHP 8.1并开始测试我的旧项目。我使用了过滤器FILTER_SANITIZE_STRING,如下所示:

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

现在我遇到了这个错误:

已弃用:常量 FILTER_SANITIZE_STRING 已被弃用

当我使用 FILTER_SANITIZE_STRIPPED 时也出现相同情况:

已弃用:常量 FILTER_SANITIZE_STRIPPED 已被弃用

我应该使用什么替代它们呢?

5个回答

81

这个过滤器的目的不明确。很难说它实际上想要达到什么目的或者应该在何时被使用。由于它的名称,它还会与默认的字符串过滤器混淆,但实际上默认的字符串过滤器称为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);
}

不要试图对输入进行消毒处理。转义输出。


4
请注意,htmlspecialchars 可能不是一对一的替换。FILTER_SANITIZE_STRING 会去除标签。在这种情况下,使用 strip_tags 会很有用。 - Louis Charette
1
如果您需要一对一的替换,可以使用我创建的polyfill。 strip_tags 也不是一对一的替换。 - Dharman
3
我理解编码输出的必要性。然而,决定不使用FILTER_UNSAFE_RAW过滤输入是我个人认为非常糟糕的决定。没有人希望在数据库中出现混乱。我确实非常需要FILTER_SANITIZE_STRING。 - Ondrej
2
@Dharman,FILTER_SANITIZE_SPECIAL_CHARS作为FILTER_SANITIZE_STRING的替代方案怎么样?或者可以通过循环遍历values来实现。 - Motivated
1
@Motivated 是的,那正是我所说的。验证输入,格式化输出,永远不要对任何内容进行消毒处理(删除数据的部分)。 - Dharman
显示剩余10条评论

51

如果您想将变量转换为安全的 HTML 字符串,可以使用最接近常数 FILTER_SANITIZE_FULL_SPECIAL_CHARS 代替。


这对我有用,所以为了澄清其他人(因为有区别):来自W3:"FILTER_SANITIZE_STRING过滤器从字符串中删除标签并删除或编码特殊字符",而"FILTER_SANITIZE_SPECIAL_CHARS过滤器HTML转义特殊字符"。 - Design.Garden

11

根据文档,你应该用htmlspecialchars()替换它。

FILTER_SANITIZE_STRING

去除标签并对双引号和单引号进行HTML编码,可选择去除或编码特殊字符。通过设置FILTER_FLAG_NO_ENCODE_QUOTES可以禁用引号的编码。(自PHP 8.1.0起已弃用,请改为使用htmlspecialchars())

FILTER_SANITIZE_STRIPPED

"string"过滤器的别名。(自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);
}

-8

可以轻松地用这个替换:

FILTER_UNSAFE_RAW

1
它可以被替换为那个,但是行为是不同的。如果 FILTER_SANITIZE_STRING 被依赖于保护免受恶意输入的影响,按照您的建议进行切换将会移除该保护。 - thelr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接