2010-09-24 116 views
2

由於某些原因,對以下AES密鑰使用DBI的綁定參數功能會導致查詢無法找到任何行。爲什麼使用DBI的變量綁定導致MySQL查詢失敗?

use strict; 
use warnings; 
use DBI; 

my $dbh = DBI->connect('dbi:mysql:database=thedb;host=localhost'); 

my $aes_key = 'X`[email protected]_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中。不過,我懷疑這個問題或類似的問題。

回答

4

當你將一個變量綁定到佔位符時,MySQL使用的正是Perl變量中的內容。當你將一個變量插入到SQL語句中時,MySQL會將其視爲字符串文字。

MySQL通過刪除反斜槓來處理未知的反斜槓轉義。作爲MySQL字符串文字,'\S''S'是等效的。當您使用佔位符時,Perl變量中的'\S'等同於'\\S'作爲MySQL字符串文字。

看起來您已使用字符串文字在數據庫中錯誤地存儲了密鑰,所以現在使用佔位符時無法找到它。我敢打賭,如果你改變了線路,你初始化$aes_key

my $aes_key = 'X`[email protected]_BISgY[S%/<iaB>&VXd5zDA+'; # note missing backslash 

然後,因爲這是關鍵的是,MySQL已經實際使用效果將變爲

31 
1 
1 

3

我看到$ aes_key中存在一個轉義的「S」,但它對變量沒有任何影響,因爲\ S在Perl中不是有效的轉義序列。不過,我懷疑這個問題或類似的問題。

它是,它不是。使用DBI佔位符,根本沒有對轉義序列的解釋。

的問題是,MySQL的一直解釋你的轉義序列,當你粘貼的鑰匙插入SQL:

mysql> select 'X`[email protected]_BI\SgY[S%/<iaB>&VXd5zDA+', length('X`[email protected]_BI\SgY[S%/<iaB>&VXd5zDA+') as len; 
+---------------------------------+-----+ 
| X`[email protected]_BISgY[S%/<iaB>&VXd5zDA+ | len | 
+---------------------------------+-----+ 
| X`[email protected]_BISgY[S%/<iaB>&VXd5zDA+ | 31 | 
+---------------------------------+-----+ 
1 row in set (0.00 sec) 

看到了嗎?沒有反斜槓(如果你在一個沒有特殊含義的字符前加一個反斜槓,你只會得到相同的字符,但沒有反斜線)。所以當你把密鑰正確地傳遞到mysql 它不起作用,因爲你以前使用不正確。