PHP&;MySQL比较密码

PHP&;MySQL比较密码,php,mysql,login,passwords,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 W

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

这就是我正在做的(从一堆组合中…):

<?

$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.";

?>
一些要点:

  • 不要在查询字符串中插入字符串数据。特别是用户提供的数据。如果我使用“Robert”登录,会发生什么?删除表客户?。使用转义例程,或者(更好的)使用准备好的语句和绑定参数
  • 不要在数据库中存储明文密码。(你在这方面没问题)
  • 不要从数据库中检索密码
我通常是这样做的:

$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.";
}

首先,确保在查询中使用变量之前正确转义-使用mysql\u real\u escape\u string()

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

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

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

我看到您正在数据库中存储密码哈希,但为了其他读者的利益,请不要在数据库中以纯文本形式存储密码。你不想这样

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

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

 if (hash_equals($users_dbpassword, $users_password)) {
      //pass is good
 } else {
       // pass failed
 }
您还应该对密码应用随机密码。为每个用户的帐户存储不同的salt值。这有助于击败字典攻击和其他攻击

您应该学会使用扩展,而不是旧的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=?密码=?
但我不喜欢这样做。如果执行此操作,则无法知道是因为登录不存在,还是因为用户提供了错误的密码而导致查找失败

当然,您不应该向用户透露导致登录尝试失败的原因,但您可能需要知道,以便记录可疑活动


@Javier在他的回答中说,您不应该从数据库中检索密码(在本例中是密码哈希)。我不同意

Javier显示了在PHP代码中调用
md5()
,并将结果哈希字符串发送到数据库。但这不支持轻松地添加密码。在PHP中进行哈希之前,必须执行单独的查询来检索该用户的salt

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


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

从FORM POST方法获取用户密码,并转换$\u POST['password']//从表单//转换为php/jsp/任何其他格式,然后与数据库中的格式化密码进行比较

通常,当您可以比较数据库中存在的md45(“{$\u POST['password']}”)=时,使用md5加密;
或者通常mysql在创建密码时使用password(“your password”)命令,因此首先将$_POST['password']协调到mysqli_查询和mysqli_fetch_数组中,以获得加密的密码值,然后进行比较。

大于PHP5.6,可以使用哈希_比较函数

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

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

我们称他为小Bobby Tables。您可能应该指出,这里没有使用本机PHP代码。bindvalue()让我有点困惑,尤其是在php.net上找不到它之后。最终在网上找到了PHP数据对象(PDO),它涵盖了您的示例中的信息。我们更愿意在技术上详细解释如何清理用户输入。与其有一个正常工作的网站,还不如有一个安全的网站。@Grant:你在开玩笑吧?请注意,此页面上的答案已经过时,因此不安全,请看一看。你的代码中只缺少一点。mysqli_prepare()接受两个参数——第一个是mysqli_connect()语句的结果。因为我使用的是mysql_connect(),所以它不起作用。但是经过修改后,它工作得很好。谢谢你的帮助。谢谢你的帮助,我已经修好了。不过,我没有显示连接到数据库。假设你有一个活的$mysqli对象。mysqli是一个可怕的bug,无法使用(很遗憾)@cletus:与什么相反?PDO_mysql?mysql扩展?PHP本身?@Bill:mysqli有两个严重的问题,其中一个(长文本列上的seg错误)已经三年没有被修复了。另一个是随机的“金丝雀问题”错误(或者类似的错误;但我在这一点上犯了错误,在mysql上做得很好)。是mysql或PDO。实际上,此函数不应用于比较密码散列(可比较的散列不适用于密码),而是使用并生成散列。