我看到您将密码的哈希值存储在数据库中,但为了其他读者的利益,切勿将密码以纯文本形式存储在数据库中。你不想像Monster.com.uk 一样!
您应该使用比MD5(). 理想情况下,您应该使用 SHA256。在 PHP 中使用该hash()函数可以使用此哈希方法。
您还应该对密码应用随机盐。为每个用户的帐户存储不同的盐值。这有助于击败字典攻击和彩虹表攻击。
你应该学会使用mysqli扩展而不是旧的 mysql 扩展。Mysqli 支持参数化查询,因此可以减少对某些 SQL 注入攻击的脆弱性。
这是一些示例代码。我还没有测试它,但它应该非常接近工作:
$input_login = $_POST['login'];
$input_password = $_POST['password'];
$stmt = $mysqli->prepare("SELECT password, salt FROM customer WHERE login = ?");
$stmt->bind_param("s", $input_login);
$stmt->execute();
$stmt->bind_result($password_hash, $salt);
while ($stmt->fetch()) {
$input_password_hash = hash('sha256', $input_password . $salt);
if ($input_password_hash == $password_hash) {
return true;
}
// You may want to log failed password attempts here,
// for security auditing or to lock an account with
// too many attempts within a short time.
}
$stmt->close();
// No rows matched $input_login, or else password did not match
return false;
其他一些人建议查询应该测试,login = ? AND password = ?但我不喜欢这样做。如果这样做,您将无法知道查找失败是因为登录名不存在,还是因为用户提供了错误的密码。
当然,您不应向用户透露导致登录尝试失败的原因,但您可能需要知道,以便记录可疑活动。
@Javier 在他的回答中说,您不应该从数据库中检索密码(或本例中的密码哈希)。我不同意。
Javier 展示了调用md5()PHP 代码并将生成的哈希字符串发送到数据库。但这不支持轻松地对密码进行加盐。您必须执行单独的查询来检索此用户的盐,然后才能在 PHP 中执行散列。
另一种方法是通过网络将明文密码从 PHP 应用程序发送到数据库服务器。任何窃听您网络的人都可以看到此密码。如果您记录了 SQL 查询,则任何有权访问日志的人都可以看到密码。有上进心的黑客甚至可以在垃圾箱中寻找旧的文件系统备份媒体,并可能以这种方式读取日志文件!
较小的风险是将密码哈希字符串从数据库中提取到 PHP 应用程序中,将其与用户输入的哈希值(也在 PHP 代码中)进行比较,然后丢弃这些变量。