PHP& MySQL比较密码

时间:2009-01-28 18:40:34

标签: php mysql login passwords

如何检查用户是否输入了正确的密码才能登录?

这就是我所做的(在一堆组合......中):

<?

$login = $_POST['login'];
$password = $_POST['password'];

mysql_connect('localhost', 'root', 'abc123');

mysql_select_db('aun_vox') or die(mysql_error());

$q = mysql_query("SELECT password FROM customer WHERE login='$login'");
$db_pass = mysql_result($q, 0);

if(md5($password) == $db_pass)
{
    echo "You did it.";
}

else echo "Wrong.";

?>

正如我从输出中看到的那样,mysql_result位出现了问题,但我无法找到正确的方法。

有人可以帮忙。

5 个答案:

答案 0 :(得分:17)

我看到您在数据库中存储了密码的哈希值,但为了其他读者的利益,从不以纯文本形式存储数据库中的密码。你不想成为like Monster.com.uk

您应该使用比MD5()更强的散列函数。理想情况下,您应该使用SHA256。使用hash()函数在PHP中可以使用此哈希方法。

您还应该随机salt应用于密码。为每个用户的帐户存储不同的盐值。这有助于打败字典攻击和rainbow table攻击。

您应该学习使用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显示在PHP代码中调用md5()并将生成的哈希字符串发送到数据库。但这并不支持轻松保存密码。您必须先执行单独的查询以检索此用户的salt,然后才能在PHP中执行哈希。

另一种方法是通过网络从您的PHP应用程序向数据库服务器发送明文密码。任何窃听您网络的人都可以看到此密码。如果您记录了SQL查询,那么获得日志访问权限的任何人都可以看到密码。有动力的黑客甚至可以通过垃圾站潜水查找旧的文件系统备份媒体,并可能以这种方式读取日志文件!

较小的风险是从数据库中将密码哈希字符串提取到PHP应用程序中,将其与用户输入的哈希值(也在PHP代码中)进行比较,然后丢弃这些变量。

答案 1 :(得分:2)

首先,确保在查询中使用它们之前正确转义变量 - 使用mysql_real_escape_string()。

那么,为什么不使用MySQL MD5函数来检查查询中的有效登录?

SELECT login FROM customer WHERE login='$login' AND password = MD5('$password')

然后只使用mysql_num_rows()来计算返回的行数。

答案 2 :(得分:1)

一些观点:

  • 请勿在查询字符串中插入字符串数据。特别是用户提供的数据。如果我使用“Robert'; drop table customer”登录会发生什么?使用转义例程,或者(更好)使用预准备语句和绑定参数。
  • 请勿在您的数据库中存储明文密码。 (你对此很好)
  • 请勿从数据库中检索密码。

我通常做的是:

$q = preparestatement ("SELECT id FROM customer WHERE login=? AND password=?");
bindvalue ($q, $_POST['login']);
bindvalue ($q, md5($_POST['password']));
$id = execprepared ($q);

if($id) {
    echo "You did it.";
} else {
    echo "Wrong.";
}

答案 3 :(得分:0)

从FORM POST方法获取用户密码并将$ _POST ['password'] //从表单//转换为适当格式的php / jsp / any,然后与数据库中的格式化密码进行比较

通常使用md5加密,您可以比较md45('{$ _ POST ['password']}')=存在于您的数据库中; 或者通常mysql在创建密码时使用密码('你的密码')命令,因此首先将你的$ _POST ['密码']与mysqli_query和mysqli_fetch_array进行对比,以获得加密的密码值,然后进行比较。

答案 4 :(得分:0)

大于PHP 5.6,您可以使用hash_compare函数。

 $users_password = hash(sha256,$salt.$post_password);

 if (hash_equals($users_dbpassword, $users_password)) {
      //pass is good
 } else {
       // pass failed
 }

http://php.net/manual/ru/function.hash-equals.php