我将md5哈希存储在cookie和数据库中。我有一个函数,validate_cookie()
,读取此cookie并查询数据库以查找与此哈希关联的用户。
validate_cookie()
调用另一个函数get_user_data()
来执行实际查询。get_user_data()
被其他一些函数和脚本调用,因此它发送的查询非常通用。函数如下:
function get_user_data($info,$password=Null,$source=Null)
{
if(!$source)
{
$query = "SELECT * FROM `users` WHERE `id` = '".mysql_real_escape_string($info)."' OR `email` = '".mysql_real_escape_string($info)."' OR `cookie`='".mysql_real_escape_string($info)."'"; //Check to see if $info matches any column
}
else { $query = "SELECT * FROM `users` WHERE `".mysql_real_escape_string($source)."_token` ='".mysql_real_escape_string($info)."'";} //we got a social token
$result = mysql_query($query);
if($result)
{
$row = mysql_fetch_array($result);
if($password)
{
if(crypt($password, $row['password']) == $row['password']) //password matching
{
return $row;
} else {return "Password does not match!";}
}
else { return $row; }
}
else { return "Could not get result from database!";}
}
在这种情况下,重要的查询位于if(!source){}
块内。随着validate_cookie()
调用get_user_data()
这个查询变成的方式(我已经测试过它确实变成了这个):
SELECT * FROM `users` WHERE `id` = '8sd8sdvsasdliwerhnbzo823' OR `email`='8sd8sdvsasdliwerhnbzo823' OR `cookie`='8sd8sdvsasdliwerhnbzo823'
由于 id
是一个 int 字段,并且email
中的所有内容都经过验证,因此应从此查询中选择的唯一行是具有匹配cookie
字段的行。
但是,无论是从 PHP 脚本调用此查询还是从 PHPMyAdmin 手动调用此查询,这将始终同时选择目标行和另一个行:一个在其cookie
字段中只有NULL
的测试用例。稍微更改哈希(以便它根本不应该匹配任何内容)仍然会选择相同的测试用例。
我的查询是否以我无法理解的方式格式不正确?是否有一些晦涩的OR
用途允许匹配NULL
字段?任何帮助将不胜感激。
附言在我被告知我真的应该使用mysqli
之前,是的,我知道这一点。 mysql
是老板的命令。
> http://sqlfiddle.com/#!2/0b0832/10/0
它正在将您的哈希转换为整数。 您的测试 ID 为 3。 您的哈希值以 3 开头。 它正在使这些人平等。
select cast('3b38f280e0203d7998a0d0898095ed56' as unsigned) as x
产量 3
像这样修复它:
SELECT id, email, password, cookie,
case when `email` = '3b38f280e0203d7998a0d0898095ed56' then 'email'
when `id` = '3b38f280e0203d7998a0d0898095ed56' then 'id'
when `cookie` = '3b38f280e0203d7998a0d0898095ed56' then 'cookie'
else 'else' end as wtf
FROM `users`
WHERE
cast(`id` as char) = '3b38f280e0203d7998a0d0898095ed56' or
`email` = '3b38f280e0203d7998a0d0898095ed56' or
`cookie` = '3b38f280e0203d7998a0d0898095ed56'
如果您传入 ID = 3,这仍然有效
当且仅当您确定 sql 语句演变为类似以下内容时:
select a,b,[c ...] from mytable where a='something' or b='something' [or ...]
与 a,b [...] 不空
你只应该得到一行"a"或"b"不为空并且是"某事"。如果没有,您的数据库/系统/DiRiver 或其他问题有问题
有时"其他人错了"
这么说,但这是我所做的一个经验(就我而言php_db2有时我只是没有得到结果)。
特别是 - 再说一遍 - 如果您确定您的语句在运行时如何演变,如果使用"本机"工具,MySQL 管理员在这里给出相同的 - 错误 - 结果,则存在问题,不在您的范围内
如果(看起来像)您的数据库/驱动程序/安装中存在 en 错误,您可以尝试使用类似
select from ... where (a='som' and a is not null) or (b='som' and b is not null...) and so on
考虑用"TODO:等待正确的数据库安装"左右来标记它
顺便说一句: