PDO选择预处理语句不起作用

时间:2014-08-22 00:03:37

标签: php pdo

这是源代码的代码片段,我用它来练习我的PHP技能。提交登录表单后,我尝试查看用户使用登录表单提交的用户名和密码是否与存储在数据库中的用户名和密码匹配。如果是,那么"您的用户名和密码与我所拥有的相符!" (显然这不是最后的回声,只是为了看看它带来的回声是什么)。如果我给出正确的信用卡(用户/通行证)或不正确的信用卡,它会回复出来"您的用户名和密码与我所拥有的不相符!"块。我没有看到代码有任何问题,我没有想法。

config.php(我已经包含)中的部分代码是数据库的设置,有一个注册表和几个字段,其中存在用户名和密码字段,因此名称。

user是用户名登录表单上的名称标签的值,pass是密码登录表单上的名称标签的值。

<?php
  include("config.php");
  if(isset($_POST['submit'])) {
      $stmt = $db->prepare("SELECT * FROM registration WHERE username = :username AND password = :password");
      $stmt->execute(array("username" => $_POST['user'], "password" => $_POST['pass']));
      $result = $stmt->fetch(PDO::FETCH_ASSOC);

      if(($_POST['user'] == $result['username']) && $_POST['pass'] == hash("sha256",$result['password'])) {
          echo "Your username and password matches what I have! <html><br /></html>";
      } else {
          echo "Your username and password DOES NOT matches what I have! <html><br />    </html>";
      }
  }
?>

1 个答案:

答案 0 :(得分:2)

您有一个向后密码存储的概念:您的代码将$_POST['pass']与数据库中字符串的哈希值进行比较。那么用户需要输入密码的SHA256哈希值?并将明文密码存储在数据库中?我不这么认为。

应该是相反的方式。您允许用户输入他们的密码,然后您输入他们输入的字符串。然后将其与存储在数据库中的内容进行比较,该数据库也应该是一个散列字符串。

$pass_hash = hash("sha256", $_POST["pass"]);
$stmt = $db->prepare("SELECT * FROM registration WHERE username = :username AND password = :password");
$stmt->execute(array("username" => $_POST['user'], "password" => $pass_hash));

您不必使用if()来测试结果。只测试查询是否返回零行。如果它返回任何行,那么你找到了一个匹配。

也不要假设fetch()返回一行。如果没有行,则返回NULL,因此将该行用作关联数组将引发错误。在解除引用之前测试该行是否为非空。

if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    // username and password matched a row
    echo "Your username and password matches what I have! <html><br /></html>";
} else {
    // no matching username
    echo "Your username and password DOES NOT matches what I have! <html><br />    </html>";
} 

这是我更喜欢的替代变体:我只是查找与用户名匹配的行,然后返回哈希密码字符串。然后我在应用程序代码中比较。这样我可以判断他们是否提供了合法的用户名,但密码错误。您不一定要向用户透露该信息,但您可能希望在应用中跟踪它,因此如果有人为同一用户名尝试了几十个错误密码,您可以锁定用户名或为操作员记录警报或东西。

$stmt = $db->prepare("SELECT password FROM registration WHERE username = :username");
$stmt->execute(array("username" => $_POST['user']));
if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $pass_hash = hash("sha256", $_POST["pass"]);
    if ($pass_hash == $row['password']) {
        echo "Your username and password matches what I have! <html><br /></html>";
    } else {
        // username exists, but wrong password
        echo "Your username and password DOES NOT matches what I have! <html><br />    </html>";
    }
} else {
    // no matching username
    echo "Your username and password DOES NOT matches what I have! <html><br />    </html>";
}