【问题标题】: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....

【问题讨论】:

    标签: php mysql regex escaping


    【解决方案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 解释没有任何作用,这就是问题所在。
      猜你喜欢
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      • 2011-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      相关资源
      最近更新 更多