常量 FILTER_SANITIZE_STRING 已弃用

Constant FILTER_SANITIZE_STRING is deprecated

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

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

现在我得到这个错误:

Deprecated: Constant FILTER_SANITIZE_STRING is deprecated

当我使用 FILTER_SANITIZE_STRIPPED:

时也会发生同样的情况

Deprecated: Constant FILTER_SANITIZE_STRIPPED is deprecated

我可以用什么代替它?

此过滤器的用途不明确。很难说它究竟是为了完成什么或何时应该使用它。由于其名称,它也与默认字符串过滤器混淆,而实际上默认字符串过滤器称为 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);
    }
    

Don’t try to sanitize input. Escape output.

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

根据我们的经验,FILTER_SANITIZE_STRING 对表单非常有用,因为当输入表单是单个文本输入时,我们找不到任何转义 HTML 的理由。

即使通过任何更改 JS 代码确实登陆了数据库,它的内容也是乱码,因为引号、单引号和 < > 被转换为 HTML 等价物。如果我们按原样回显字段内容,用户仍然是安全的,因为标签是乱码,不会运行。当然我们可能是错的,但我们没有遇到任何与过滤器直接相关的问题。

有些键盘没有正确的键盘语言,因此,他们在字段中输入的引号可能会或不会导致弯引号,这不利于将该字符串读回输入字段.

有人可能会争辩说,必须对特定字符串的输出进行转义,但是当您可以在将数据输入数据库之前清理字符串时,为什么还要多花两行代码来对 N 个不同输出的输出进行转义呢?

我们从未听说过 FILTER_SANITIZE_STRING 有防止 XSS 的目标,因为我们并没有完全将过滤器用于该特定任务。

在 link 中“不要尝试清理”没有提到使用 FILTER_SANITIZE_STRING。

他们给了我们一个例子(我稍微修改了一下):

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

这产生:

SELECT * 来自用户名 = 'Robert');删除 TABLE 用户的

不出所料,这是一个 SQL 注入。

但是,如果我们过滤它:

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

这产生:

SELECT * 来自用户名 = 'Robert');删除 TABLE 用户的

我们将结束询问名为“Robert&#39;”的用户名;DROP TABLE users”并且查询将return没有结果。

我们确实希望 PHP 维护者能够回过头来看看过滤器的用处并保留它。但如果没有,那么我们只需要使用 polyfill

它可以很容易地替换为:

FILTER_UNSAFE_RAW