0

我最近在一个程序中发现了一个有趣的错误,它使用他们的私钥为特定客户选择数据。考虑以下:

SELECT `id` FROM (`customers`) WHERE `authenticationKey` = '#09209!ko2A-' LIMIT 1

密钥在请求时提供,并在查询之前进行了适当的清理。但是,未能提供密钥(应该在之前捕获;忽略它),将产生类似于以下的查询:

SELECT `id` FROM (`customers`) WHERE `authenticationKey` = 0 LIMIT 1

它将从customers-table 返回一行 - 尽管它存储了正确的字符串键,例如在第一个示例中。

authenticationKey-field 的类型为VARCHAR(1024)

我的猜测是,这与松散的比较有关。是什么导致了这个问题,如何正确避免?

4

2 回答 2

4

MySQL 将尝试将数据强制转换为可比较的类型。在这种情况下,它将尝试将字符串转换为数字。任何无法理解的字符串都默认为 0。

select 0 = 'banana'

看到这个在行动。

将您的查询与'0'而不是进行比较0会修复它。

Example SQLFiddle

于 2013-11-10T21:21:26.070 回答
1

MySQL 将 的前导字符隐式转换authenticationKey为 int,直到找到一个不是有效数字的字符。我猜所有以非数字字符开头的行都被视为 0。

例如,这会产生 'b',因为强制的 int 值为 1:

select (case when '1abc' = 0 then 'a' else 'b' end);

但这会产生 'a',因为前导 char 不是有效数字,所以强制 int 值为 0:

select (case when '#1abc' = 0 then 'a' else 'b' end);

应用程序应该避免这种情况。0毕竟,为什么在没有给出密钥的情况下查询呢?

于 2013-11-10T21:23:08.950 回答