简体   繁体   English

PDO选择准备好的语句不起作用

[英]PDO select prepared statement does not work

This is a snippet of code from source code, which I made to practice my PHP skills. 这是源代码的代码段,是我用来练习PHP技能的代码段。 After submitting the login form, I try to see if the username and password that the user submitted using the login form matches with the one stored on database. 提交登录表单后,我尝试查看用户使用登录表单提交的用户名和密码是否与数据库中存储的用户名和密码匹配。 If yes then "Your username and password matches what I have!" 如果是,则“您的用户名和密码与我的密码匹配!” (obviously this is not going to be the final echo but just to see what echo out of the two will it bring). (显然,这不会是最终的回声,而只是要看看两者之间会带来什么回声)。 If I give correct creds (user/pass) or incorrect one, it echoes out "Your username and password DOES NOT matches what I have!" 如果我给出正确的凭据(用户/密码)或凭据不正确,它会回显“您的用户名和密码与我的不匹配!” block. 块。 I don't see any problem with the code, I ran out of ideas. 我看不到代码有任何问题,我的想法已经用完了。

Part of the code inside config.php (which I have included) is a setup of the database, with a table of registration and few fields, of which username and password fields does exist hence the names. config.php(我包括在内)中的部分代码是数据库的设置,具有注册表和少量字段,其中确实存在用户名和密码字段,因此也包含名称。

user is value of the name tag on login form for Username and pass is value of the name tag on login form for Password. 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>";
      }
  }
?>

You've got one concept of password storage backwards: your code compares $_POST['pass'] to the hash of the string in the database. 您有一个向后存储密码的概念:您的代码将$_POST['pass']与数据库中字符串的哈希值进行比较。 So users are required to enter a SHA256 hash of their password? 因此,要求用户输入密码的SHA256哈希吗? And you store plaintext password in the database? 并将明文密码存储在数据库中? I don't think so. 我不这么认为。

It should be the other way around. 情况应该相反。 You allow users to enter their password, then you hash the string they enter. 您允许用户输入密码,然后对他们输入的字符串进行哈希处理。 Then compare that to what's stored in the database, which should also be a hashed string. 然后将其与数据库中存储的内容(也应为哈希字符串)进行比较。

$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));

You don't have to use an if() to test the results. 您不必使用if()来测试结果。 Just test if the query returns zero rows, or not. 只需测试查询是否返回零行即可。 If it returns any rows, then you found a match. 如果返回任何行,那么您找到了一个匹配项。

Also don't assume fetch() returned a row. 也不要假设fetch()返回了一行。 If there was no row, it returns NULL, so using that row as an associative array will throw an error. 如果没有行,则返回NULL,因此将该行用作关联数组将引发错误。 Test to see if the row is non-null before dereferencing it. 在取消引用行之前,测试以查看该行是否为非空。

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

Here's an alternative variation I prefer: I just look for a row matching the username, and I return the hashed password string. 这是我更喜欢的另一种变体:我只是寻找与用户名匹配的行,然后返回哈希密码字符串。 Then I compare in application code. 然后,我在应用程序代码中进行比较。 This way I can tell if they gave a legitimate username, but the wrong password. 通过这种方式,我可以判断他们是否提供了合法的用户名,但密码错误。 You don't necessarily want to reveal that to the user, but you might want to track it in your app so if someone is trying dozens of wrong passwords for the same username, you could lock the username or log an alert for the operator or something. 您不一定要向用户透露此信息,但您可能想在应用程序中对其进行跟踪,因此,如果有人尝试为同一用户名输入数十个错误的密码,则可以锁定用户名或为操作员或用户记录警报的东西。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM