当用户尝试登录时,有两种方法可以检查用户是否有效。
方法1:执行以下查询并检查返回的行数是否与1相同。
SELECT * FROM users WHERE username = $_POST['username'] AND password = md5($_POST['password'])
方法2:执行查询,然后检查密码匹配。
SELECT * FROM users WHERE username = $_POST['username']
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)){
if($row['password'] == md5($_POST['password'])) $logged_in = TRUE;
}
这些方法中的一种优于另一种吗?如果是这样,为什么呢?
答案 0 :(得分:4)
使用密钥,盐和密码。 md5
不安全。
在服务器上,存储密钥:
$key = 'fPu6AY;h0-5Q>cIel,@n2$gickGs9{ys~+DT,v|Mz-]~EU3tuj18|~Ch#1_$)fGR';
当用户注册时会生成唯一 salt,并将其与加密密码一起存储在服务器上:
| SALT | PASSWORD | --------------------------------------------------------------------------------- | jAcTgi~4(Z | 877236d15a7b7a1f36febc49e58b142d70d72cf7d6e54dcfb252d7cde6b62a2d |
密码加密如下:
$hash = hash('sha256', $keyFromServer . $saltFromDb . $userPassword);
然后必须使用方法2获取salt和hash以将其与数据库密码进行比较。
答案 1 :(得分:2)
方法2是首选,因为您可以使用像PHPass这样的库。它还使您能够告诉用户他们键入了无效的用户名,而不是让他们猜测他们输错了其中一个。 Aarolama对md5不安全是正确的。不幸的是,SHA系列也不是。这两个都是文件哈希,用于唯一标记和识别文件。使用加密哈希来保护密码,例如河豚。 PHPass为您处理了很多安全问题。盐应该是随机生成的,并且每个用户都是唯一的,唯一可以让它们供自己使用的方法是使用第二种方法。
答案 2 :(得分:0)
要添加到 FreshPrinceOfSO 的答案,不要简单地将密钥与salted明文连接起来 - 改为使用HMAC方法:
$hash = hash_hmac('sha256', $saltFromDb . $userPassword, $keyFromServer);
关于HMAC的更多详细信息可以在Wikipedia和RFC 2104中找到,同时解释为什么琐碎的方法存在缺陷。值得注意的是,与单独的基础哈希算法相比,HMAC受冲突的影响要小得多,即。即尽管核心算法和输出大小相同,它们仍然更安全。
顺便说一下,关于输出大小。在上述RFC 2104的第5节中,声明截断的散列(原始大小的一半或更大),同时减少可能值的总数,同时使得通过强力恢复明文更加困难,如要检查的完整哈希值对攻击者不可用。这也适用于非HMAC哈希值。