Почему использование привязки переменных DBI приводит к сбою запроса MySQL? - PullRequest
2 голосов
/ 24 сентября 2010

По какой-то причине использование функции параметра привязки DBI для приведенного ниже ключа AES приводит к тому, что запрос не может найти строки.

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 не является допустимой escape-последовательностью в Perl.Однако я подозреваю, что проблема в чем-то подобном.

Ответы [ 2 ]

4 голосов
/ 24 сентября 2010

Когда вы связываете переменную с заполнителем, MySQL использует именно то, что находится в переменной Perl.Когда вы интерполируете переменную в оператор SQL, MySQL обрабатывает ее как строковый литерал.

MySQL обрабатывает неизвестные экранированные символы обратной косой черты, удаляя обратную косую черту.Как строковые литералы MySQL, '\S' и 'S' эквивалентны.Когда вы используете заполнители, '\S' в переменной Perl эквивалентно '\\S' в качестве строкового литерала MySQL.

Похоже, что вы неправильно хранили ключ в базе данных, используя строковый литерал, поэтомутеперь его нельзя найти при использовании заполнителя.Держу пари, что если вы измените строку, в которой вы инициализируете $aes_key, на

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

, тогда результаты изменятся на

31
1
1

, потому что это ключ, которым фактически был MySQLиспользование.

3 голосов
/ 24 сентября 2010

Я вижу, что в $ aes_key есть экранированная буква "S", но она не оказывает никакого влияния на переменную, поскольку \ S не является допустимой escape-последовательностью в Perl.Я подозреваю, что или что-то подобное является проблемой, хотя.

Это так и не так.С заполнителями DBI вообще нет интерпретации escape-последовательностей.

Проблема в том, что mysql имеет интерпретирует ваши escape-последовательности при вставке ключа в 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 правильно , он не работает, потому что вы использовали его ранее неправильно.

...