在 MySQL 中转义用户输入正则表达式的最佳方法是啥?

Posted

技术标签:

【中文标题】在 MySQL 中转义用户输入正则表达式的最佳方法是啥?【英文标题】:What's the best way to escape user input for Regular Expressions in MySQL?在 MySQL 中转义用户输入正则表达式的最佳方法是什么? 【发布时间】:2011-04-16 11:49:01 【问题描述】:

我想获取用户输入,表示为 $dangerous_string,并将其用作 mysql 查询中 RegEx 的一部分。

执行此操作的最佳方法是什么?我想将用户的字符串用作文字——如果它包含任何在 MySQL RegEx 中表示某种含义的字符,那么这些字符实际上不应该影响我的正则表达式。

$dangerous_string = $_GET["string"];
//do something here
$dangerous_string = what_goes_here($dangerous_string);
$sql = "SELECT * FROM table WHERE search_column REGEX '" . $mysqli->real_escape_string("[[:<:]]$dangerous_string") . "'";

//etc....

【问题讨论】:

【参考方案1】:

AFAIK,MySQL 正则表达式没有本地转义方式。您可以使用 preg_quote (http://www.php.net/manual/en/function.preg-quote.php) 在 PHP 中执行此操作,这可能会为您完成这项工作,但显然不是为此目的而设计的。

如果我遇到您的情况,我首选的方法是在 PHP 中构建一个正则表达式白名单,然后您可以将其应用于您的危险字符串:

$safeString = preg_replace('/[^\w]/','',$dangerousString);

这会从您的字符串中删除所有非单词字符(即除 A-Za-z0-9_ 之外的任何字符)。

注意,我相信给出的其他答案不会删除/转义正则表达式特殊字符,我相信这是您的要求。

【讨论】:

【参考方案2】:

使用preg_quote 并手动替换&amp;

preg_quote 接受一个字符串并用反斜杠转义特殊字符。它适用于 PHP 正则表达式,而不是 MySQL 正则表达式,它不会转义 MySQL 所需的 &amp;。所以我们只需要像这样修改它:

function escape_regex_for_mysql($dangerous_string) 
    return preg_replace('/&/', '\\&', preg_quote($dangerous_string));

请注意,您仍应在顶部使用准备好的语句(或 $mysqli-&gt;real_escape_string),如下所示:

$query = $wpdb->prepare(
    'SELECT * FROM table WHERE search_column REGEXP %s',
    '[[:<:]]' . escape_regex_for_mysql($dangerous_string)
);

理由:

让我们看看 MySQL 的文档,看看哪些字符需要转义。 The documentation 说:

MySQL >= 8.0.4 使用 Unicode 国际组件 (ICU) 实现正则表达式支持,它提供完整的 Unicode 支持并且是多字节安全的。

那么让我们看看the documentation for the ICU project:

\(在集合之外)引用以下字符。必须引用才能被视为文字的字符是 * ? + [ ( ) ^ $ | \ .

\(在集合内)引用以下字符。必须引用才能被视为文字的字符是 [ ] \ 根据上下文可能需要引用的字符是 - &

所以需要转义的特殊字符列表是* ? + [ ] ( ) ^ $ \ . - &amp;preg_quote 转义除&amp; 之外的所有这些。它还不必要地转义了一些字符,但 MySQL 会按预期处理。

或者,您可以将&amp; 作为第二个参数添加到preg_quote 以使其被转义,例如preg_quote('AT&amp;T', '&amp;')

【讨论】:

似乎 reg exps 必须使用双斜杠而不是单斜杠才能正常工作。 str_replace('\\', '\\\\', preg_replace('/&/', '\\&', preg_quote($dangerous_string))) @luky 您的示例中的双斜杠在那里,因为您使用的是字符串文字。如果您要运行echo '\`;echo '\\&amp;',您只会看到一个反斜杠。该示例中的函数echo 仅接收一个反斜杠。使用字符串文字时需要正确转义,此外还需要使用 preg_quote 转义以用于此问题中的用途。 我没有使用任何文字,我使用的是函数 preg_quote 和变量,我相信 mysql 本身需要双斜杠。【参考方案3】:

您需要确保正确处理引号和刻度 在传递到数据库之前。最好的方法是:

   mysql_real_escape_string  ([php doc][1])

此方法在 PHP 和 C++ mysql 客户端库中都可用。

这应该确保任何 'dangerous_string' 不再危险 并且可以在 RegEx 使用的带引号的字符串中使用。

【讨论】:

对 REGEXP 解释没有任何作用,这就是问题所在。

以上是关于在 MySQL 中转义用户输入正则表达式的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

需要在正则表达式中转义的所有特殊字符的列表

如何在 oracle 中转义特殊的正则表达式字符?

应该在正则表达式中转义哪些文字字符?

在正则表达式中转义(\')单引号,它在两个单引号之间采用字符串。

你如何在 Freemarker 中转义正则表达式字符串

我必须在 Perl 预编译的正则表达式中转义哪些字符?