代码之家  ›  专栏  ›  技术社区  ›  Richard Simões

为什么使用DBI的变量绑定会导致MySQL查询失败?

  •  2
  • Richard Simões  · 技术社区  · 14 年前

    use strict;
    use warnings;
    use DBI;
    
    my $dbh = DBI->connect('dbi:mysql:database=thedb;host=localhost');
    
    my $aes_key = 'X`ku@wC_BI\SgY[S%/<iaB>&VXd5zDA+';
    print length($aes_key), "\n";
    
    my $test = $dbh->selectrow_hashref("SELECT COUNT(*) FROM users WHERE id = ?\
     AND AES_DECRYPT(enc_pass, '$aes_key') IS NOT NULL", undef, 1);
    print $test->{'COUNT(*)'}, "\n";
    
    $test = $dbh->selectrow_hashref("SELECT COUNT(*) FROM users WHERE id = ?\
     AND AES_DECRYPT(enc_pass, ?) IS NOT NULL", undef, 1, $aes_key);
    print $test->{'COUNT(*)'}, "\n";
    

    输出:

    32
    1
    0
    

    我看到里面有个逃逸的“s” $aes_key ,但事实并非如此 对变量有任何影响 \S 不是Perl中有效的转义序列。不过,我确实怀疑这是个问题。

    2 回复  |  直到 14 年前
        1
  •  4
  •   cjm    14 年前

    当您将一个变量绑定到占位符时,MySQL使用的正是Perl变量中的内容。当您在SQL语句中插入一个变量时,MySQL将其视为字符串文本。

    MySQL通过删除反斜杠来处理未知的反斜杠转义。作为MySQL字符串文本, '\S' 'S' 是等价的。使用占位符时, '\S' 在Perl中,变量等价于 '\\S'

    $aes_key

    my $aes_key = 'X`ku@wC_BISgY[S%/<iaB>&VXd5zDA+'; # note missing backslash
    

    然后结果会变成

    31
    1
    1
    

        2
  •  3
  •   hobbs    14 年前

    我看到$aes\u键中有一个转义的“s”,但它似乎对变量没有任何影响,因为\s在Perl中不是有效的转义序列。不过,我确实怀疑这是个问题。

    是的,不是的。对于DBI占位符,根本没有转义序列的解释。

    问题是mysql 在将键粘贴到SQL中时,您一直在解释转义序列:

    mysql> select 'X`ku@wC_BI\SgY[S%/<iaB>&VXd5zDA+', length('X`ku@wC_BI\SgY[S%/<iaB>&VXd5zDA+') as len;
    +---------------------------------+-----+
    | X`ku@wC_BISgY[S%/<iaB>&VXd5zDA+ | len |
    +---------------------------------+-----+
    | X`ku@wC_BISgY[S%/<iaB>&VXd5zDA+ |  31 |
    +---------------------------------+-----+
    1 row in set (0.00 sec)
    

    看到了吗?没有反斜杠(如果你把一个反斜杠放在一个没有特殊意义的字符之前,你只得到相同的字符,但是没有反斜杠)。所以当你把密钥传给mysql时 正确地 它不起作用,因为你以前用错了。