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

时间:2010-09-24 04:36:20

标签: mysql perl dbi

出于某种原因,对以下AES密钥使用DBI的绑定参数功能会导致查询无法找到任何行。

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

我看到$aes_key中有一个转义为“S”但由于\S不是有效的转义符号而不会出现对该变量产生影响Perl中的序列。不过,我确实怀疑或类似的问题。

2 个答案:

答案 0 :(得分:4)

将变量绑定到占位符时,MySQL完全使用Perl变量中的内容。将变量插入到SQL语句中时,MySQL会将其视为字符串文字。

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

看起来您使用字符串文字错误地将密钥存储在数据库中,所以现在使用占位符时无法找到它。我敢打赌,如果你改变初始化$aes_key的行到

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

然后结果将变为

31
1
1

因为这是MySQL实际使用的关键。

答案 1 :(得分:3)

  

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

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

问题是,当您将密钥粘贴到SQL时,mysql 解释您的转义序列:

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 时,它不起作用,因为您之前使用的方法不正确。