Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
338 views
in Technique[技术] by (71.8m points)

php password hash - PHP password_hash(), password_verify()

My registration script accepts a user's password and then uses PHP's password_hash function to encrypt the password, then places it in a database. When I go to login using the just created user, I'm getting the error that checks if the passwords are the same or not. In my case, they're not. What am I doing wrong when I make the call to the password_verify function in the login script?

REGISTER

if($_SERVER["REQUEST_METHOD"] == "POST"){
    function secure($data){
        $data = trim($data);
        $data = stripslashes($data);
        $data = htmlspecialchars($data);
        return($data);
    }

    $p_num = secure($_POST["p_number"]);
    $first_name = secure($_POST["first_name"]);
    $last_name = secure($_POST["last_name"]);
    $email = secure($_POST["email"]);
    $password = secure($_POST["pw"]);
    $verify_password = secure($_POST["pw_verify"]);
    $program = secure($_POST["program"]);
    $role = secure($_POST["role"]);
    $logged_in = 0;
    $registered = 0;
    $image = "../images/profile_placeholder.png";

    if($password != $verify_password){
        echo "Nope.  Passwords";
    }
    else{
        $registered = 1;
        $password = password_hash($password, PASSWORD_DEFAULT);
        $insert = "INSERT INTO `$user_table`(`user_id`, `first_name`, `last_name`, `password`, `image`, `email`, `program`, `role`, `logged_in`, `registered`) VALUES('" .$p_num ."', '" .$first_name ."', '" .$last_name ."', '" .$password ."', '" .$image ."', '" .$email ."', '" .$program ."', '" .$role ."', '" .$logged_in ."', '" .$registered ."')";
        $query = mysqli_query($connect, $insert);
        echo "Success!";
    }
}

LOGIN

if($_SERVER["REQUEST_METHOD"] == "POST"){
    $p_num = $_POST["username"];
    $pwd = $_POST["password"];

    $query = "SELECT * FROM `$user_table` WHERE `user_id` = '$p_num'";
    $result = mysqli_query($connect, $query);
    while($row = mysqli_fetch_assoc($result)){
        $user_id = "{$row['user_id']}";
        $first_name = "{$row['first_name']}";
        $last_name = "{$row['last_name']}";
        $user_name = $first_name ." " .$last_name;
        $password = "{$row['password']}";
        $image = "{$row['image']}";
        $email = "{$row['email']}";
        $program = "{$row['program']}";
        $role = "{$row['role']}";
        $status = "{$row['logged_in']}";
        $registered = "{$row['registered']}";
        if(($user_id == $p_num) && (password_verify($pwd, $password))){
            $_SESSION["id"] = $user_id;
            $_SESSION["user"] = $user_name;
            $_SESSION["program"] = $program;
            $_SESSION["pass"] = $password;
            $_SESSION["image"] = $image;
            $_SESSION["email"] = $email;
            $_SESSION["role"] = $role;
            $_SESSION["status"] = $status;
            $_SESSION["registered"] = $registered;
            $loggedin = "UPDATE `$user_table` SET `logged_in` = 1 WHERE `user_id` = '$user_id'";
        }
    var_dump($pwd);
    var_dump($password);
}

Here is what I get when I do var_dump:

string(1) "1" string(16) "$2y$10$0aysCso3b"

So clearly, the passwords are not being matched together. So, on the registration script, the password is hashed and sent to the database. Then, when the user goes to login, the login script looks at the password the user entered to login, and then checks it against the hashed password in the database using password_verify. Yet, the hashed password isn't accepting the un-hashed password as a match. What I'm not understanding is, why?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is what I use for password_hash and password_verify. Try it out as written, you can then start adding in the rest of your code once successful.

Modify table and column name(s) to suit.

N.B.: This is a basic insertion method. I suggest you use prepared statements instead.

Sidenote: The password column needs to be long enough to accomodate the hash VARCHAR(255). Consult "Footnotes".

INSERT file

<?php
$DB_HOST = 'xxx';
$DB_USER = 'xxx';
$DB_PASS = 'xxx';
$DB_NAME = 'xxx';

$conn = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
if($conn->connect_errno > 0) {
die('Connection failed [' . $conn->connect_error . ']');
}

$password = "rasmuslerdorf";
$first_name = "john";
$password = password_hash($password, PASSWORD_DEFAULT);

$sql = "INSERT INTO users (`name`, `password`) VALUES ('" .$first_name ."', '" .$password ."')";

    $query = mysqli_query($conn, $sql);
    if($query)

{
    echo "Success!";
}

else{
    // echo "Error";
    die('There was an error running the query [' . $conn->error . ']');
}

LOGIN file

<?php
// session_start();

$DB_HOST = 'xxx';
$DB_USER = 'xxx';
$DB_PASS = 'xxx';
$DB_NAME = 'xxx';

$conn = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
if($conn->connect_errno > 0) {
  die('Connection failed [' . $conn->connect_error . ']');
}

$pwd = "rasmuslerdorf";
$first_name = "john";

//$sql = "SELECT * FROM users WHERE id = 1";

        $sql = "SELECT * FROM users WHERE name='$first_name'";
        $result = $conn->query($sql);
        if ($result->num_rows === 1) {
            $row = $result->fetch_array(MYSQLI_ASSOC);
            if (password_verify($pwd, $row['password'])) {

                //Password matches, so create the session
                // $_SESSION['user'] = $row['user_id'];
                // header("Location: http://www.example.com/logged_in.php");

                echo "Match";

            }else{
                echo  "The username or password do not match";
            }

}

 mysqli_close($conn);

Footnotes:

The password column should be long enough to hold the hash. 72 long is what the hash produces in character length, yet the manual suggests 255.

Reference:

"Use the bcrypt algorithm (default as of PHP 5.5.0). Note that this constant is designed to change over time as new and stronger algorithms are added to PHP. For that reason, the length of the result from using this identifier can change over time. Therefore, it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice)."


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...