简体   繁体   中英

Mysqli: I can't login with hashed password

I'm using mysqli with hashpassword. I can't log in using my password and I don't know why. I tried all my best but its not working at all.

I'm using utf8 in my database.

This is my regiter php

<?php
if(isset($_POST["register"])){

    if(!empty($_POST['name']) && 
       !empty($_POST['studno']) &&
       !empty($_POST['password']) && 
       !empty($_POST['cpassword']) && 
       !empty($_POST['email'])) 
    {
        $name=$_POST['name'];
        $studno=$_POST['studno'];
        $password= password_hash($_POST['password'],PASSWORD_BCRYPT);
        $email=$_POST['email'];

        $con=mysqli_connect('localhost','root','') or die(mysqli_error($con));
        mysqli_select_db($con,'inventory') or die("cannot select DB");

        $query=mysqli_query($con,"SELECT * FROM users WHERE studno='".$studno."'");
        $numrows=mysqli_num_rows($query);
        if($numrows==0) {
            $sql = "INSERT INTO users(name,studno,email,password) "
                 . " VALUES('$name','$studno','$email','$password')";

            $result=mysqli_query($con,$sql);
            if ($_POST['password'] == $_POST['cpassword']) {
              if ($result) {
                  header("Location: index.php?registered=1");
              }
            } else {
               header("Location: signup.php?passwordnotmatch=1");
            }
        } else { /* numrows != 0 */
            header("Location: signup.php?alreadyinuse=1");
        }

} else {
    header("Location: signup.php?allfieldisrequired=1");
    }
}
?>

this is my log in php.

<?php
if (isset($_POST["login"])) {
    if (!empty($_POST['studno']) && !empty($_POST['password'])) {
        $studno=$_POST['studno'];
        $password=$_POST['password'];
        $con=mysqli_connect('localhost','root','') or die(mysql_error($con));
        mysqli_select_db($con,'inventory') or die("cannot select DB");
        $query=mysqli_query($con,"SELECT * FROM users WHERE studno='".$studno."' AND password='".$password."'");
        $numrows=mysqli_num_rows($query);
        if ($numrows!=0) {
            while($row=mysqli_fetch_assoc($query)) {
                $dbstudno=$row['studno'];
                $dbpassword=$row['password'];
            }
            if ($studno == $dbstudno && password_verify($dbpassword,$row['password']))) {
                session_start();
                $_SESSION['sess_user']=$studno;
                /* Redirect browser */
                header("Location: home.php");
            }
        } else {
            header("Location: index.php?error=1");
        }
    } else {
        header("Location: index.php?missing=1");
    }
}

A lot of people commented this already, but I shall post it as an answer:

There are quite some things wrong with your code:

1) You need to verify the user's input against the database, not the database against the database. What this means is that the following line will work:

password_verify($password,$row['password'])

2) Your SQL queries do not have anything to prevent sql injection, look it up.

3) Your registration page allows for user iteration, look it up.

4) Don't use a while loop to get only the first row of a database, just use a single mysqli_fetch_assoc and it will return the first row. Also use LIMIT 1 at the end of your query if you expect only one result.

5) When selecting from a database, always specify the columns you need returned unless you are absolutely sure you need ALL columns that are returned, this will speed up your queries a lot.

6) Create your mysqli connection globally (for instance, create a database.php file and connect to the database there) instead of creating a connection in every php file you use.

7) Start the session globally (for instance, create a user.php file where a session is created and the currently logged in user data is stored). Your registration page should check for a logged in user and so does the login page (why login or register if already logged in?) so you need to globally start the session somewhere.

You are verifying the same password with the same hash. Use

 password_verify($password, $dbpassowrd);

And your code is easily vulnerable to SQL Injection attacks. Validate it, sanitize user input and use prepared staments.

What you need to do is simple. Your code will never return results for this one reason "SELECT * FROM users WHERE studno='".$studno."' AND password='".$password."'" this will never return any results, as you have saved the password as hash when registering, now what happens, when a user log's in you are selecting the everything from the users table that that matches the where clause which is the studno and a password so this will never work as the password that comes from the user is unhashed therefor it will never match a hashed password. You need to remove the password from the where clause, and only have the id in the where clause.

Again this is wrong password_verify($dbpassword,$row['password'])) remember $dbpasssword and $row['password'] are the same thing remember you have this in your script $dbpassword=$row['password']; so basically your password_verify() is reading like this password_verify(storedHash,storedHash) You are verifying a stored hash against the same stored hash. password_verify() should always read like : password_virify(PasswordFromTheUserInput,StoredHash) you must verify the password from the user input against the stored hash.

So with that been said your script should look similar to this:

<?php
ob_start();
session_start();

//Extract the inputs from the user



$query  = ("SELECT  studno,password FROM users WHERE studno='" . $studno . "'");
$result = $con->query($query);
if ($result->num_rows > 0) {
    // we have the results
    while ($row = $result->fetch_assoc()) {

        $dbstudno   = $row['studno'];
        $dbpassword = $row['password'];

        // check user password against stored hash
        if (password_verify($password, $dbpassword)) {
            // password correct start a session

            $_SESSION['sess_user'] = $studno;
            /* Redirect browser */
            header("Location: home.php");
        } else {

            header("Location: index.php?error=1");

        }


    }
} else {
    header("Location: index.php?missing=1");
}
?>

Hope this helps, I might have missed something but the logic should be someway be identical to the above, I'm not good with mysqli, I use PDO most of my life.

NB: Please take into consideration the answer from @John Smith he made very important points that you need to apply.

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