出于某种原因,对以下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中的序列。不过,我确实怀疑或类似的问题。
答案 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 时,它不起作用,因为您之前使用的方法不正确。