简体   繁体   中英

PDO select prepared statement does not work

This is a snippet of code from source code, which I made to practice my PHP skills. 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.

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.

<?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. So users are required to enter a SHA256 hash of their password? 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. 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. If there was no row, it returns NULL, so using that row as an associative array will throw an error. 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>";
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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