password_verify не работает должным образом, когда данный хеш хранится в базе данных MySQL

Я делаю приложение на PHP с каркасом CodeIgniter.

Мне удалось создать страницу регистрации, которая позволяет пользователям вводить свой адрес электронной почты и пароль. Я использую password_hash(password, PASSWORD_DEFAULT) PHP функция для хранения пользовательских паролей в базе данных. Я убедился, что столбец - это VARCHAR длиной 255.

В моей пользовательской модели у меня есть следующие функции:
User_model:

public function insert_user($emailAddress, $password, $firstName, $lastName){
    $data = array(
        'email' => $emailAddress,
        'password' => password_hash($password, PASSWORD_DEFAULT),
        'firstName' => $firstName,
        'lastName' => $lastName
    );

    if(! $this->emailExists($emailAddress)){
        $this->db->insert('users', $data);
        return true;
    } else {
        return false;
    }
}

public function emailExists($emailAddress){
    $query = $this->db->get_where('users', array('email' => $emailAddress));
    if($query->num_rows() == 0){
        return false;
    }
    return true;
}

//Only use this function if you know that the email is already stored in db
public function getPassword($emailAddress){
    $query = $this->db->get_where('users', array('email' => $emailAddress));

    $row = $query->row();
    $password = $row->password;

    return $password;
}

Это мой контроллер для обработки логинов
Авторизоваться:

    class Login extends CI_Controller {

    public function index(){
        $this->load->helper(array('form', 'url'));
        $this->load->model('User_model');
        $this->load->library('form_validation');

        $this->form_validation->set_rules('password', 'Password', 'required');
        $this->form_validation->set_rules('email', 'Email', 'valid_email|required');

        if ($this->form_validation->run() == FALSE){
            $this->load->view('login'); 
        } else {        
            $email = $this->input->post('email');
            $password = $this->input->post('password');

            if($this->User_model->emailExists($email)){
                $storedPassword = $this->User_model->getPassword($email);
                if(password_verify($password, $storedPassword)){
                    echo 'passwords match';
                } else {
                    echo 'passwords dont match';
                }
            } else {
                echo 'email doesnt exist';
            }
        }
    }
}

Соответствующий вид:
авторизоваться

<html>
    <head>
        <title>Login</title>
    </head>
    <body>
        <?php echo validation_errors(); ?>
        <?php echo form_open('Login'); ?>

        <h5>Email Address</h5>
        <input type="text" name="email" value="<?php echo set_value('email');?>" size="50" />

        <h5>Password</h5>
        <input type="text" name="password" value="<?php echo set_value('password');?>" size="50" />

        <div><input type="submit" value="Submit" /></div>
        </form>
    </body>
</html>

Когда я пытаюсь войти в систему с ранее зарегистрированным адресом электронной почты и паролем, это всегда говорит о том, что пароли не совпадают.

Я понятия не имею, почему это не сработает. Могу ли я вставить или извлечь пароль из базы данных неправильно, что может изменить хэш?

1 ответ

<%php
//
// Here is PHP code I used to debug this problem
// You need to connect to a database 1st, then this will create table and do test
//
$drop = "DROP TABLE tbl_Junk";
echo $drop . '<br>';
if ($conn->query($drop) == FALSE) echo $conn->error. '<br><br>';

$create = "CREATE TABLE tbl_Junk 
(
  user_name varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  password_hash varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
)     ENGINE=MyISAM DEFAULT CHARSET=utf8;";
echo $create . '<br>';
if ($conn->query($create) == FALSE) echo $conn->error. '<br><br>';

$alter = "ALTER TABLE tbl_Junk ADD PRIMARY KEY (user_name);";
echo $alter . '<br>';
if ($conn->query($alter) == FALSE) echo $conn->error. '<br><br>';

$user_name = 'minney mouse';
echo 'user name: '     . $user_name . '<br>';
$user_password = 'secret';
echo 'user password: ' . $user_password . '<br><br>';

$original_password_hash = password_hash ($user_password, PASSWORD_DEFAULT);

echo 'password_hash() of original password hash:<br>';  
echo $original_password_hash . '<br><br>';
echo 'hex values of 1st 10 chars in original password hash:<br>';  
for ($i = 0; $i < 10; $i++) echo '0x' .             str_pad(dechex(ord($original_password_hash[$i])), 2, '0', STR_PAD_LEFT) . ' ';
echo '<br><br>';

if (password_verify ($user_password, $original_password_hash)) echo     "password_verify() from original password hash = TRUE<br><br>";
else echo "password_verify() from original password hash = FALSE<br><br>";

$insert = "INSERT INTO tbl_Junk (user_name, password_hash)  VALUES ('" . $user_name .     "', ' " . $original_password_hash . "')";
echo 'INSERT original password hash: ' .$insert . '<br>';
if ($conn->query($insert) == FALSE) echo $conn->error. '<br><br>';


$query = "SELECT password_hash FROM tbl_Junk WHERE user_name='" . $user_name . "'";
echo 'SELECT password hash: ' . $query . '<br>';
$resultSet = $conn->query($query);
$col = $resultSet->fetch_assoc(); 
$password_hash_from_db = $col['password_hash'];
echo 'password hash from database:<br>';
echo $original_password_hash . '<br><br>';
echo 'hex values of 1st 10 chars in password hash from database (NOTE 1st char maybe     0x20 (space) but not seen in hash string!!!:<br>';  
for ($i = 0; $i < 10; $i++) echo '0x' .     str_pad(dechex(ord($password_hash_from_db[$i])), 2, '0', STR_PAD_LEFT) . ' ';
echo '<br><br>';

echo 'You can remove leading space by using one of the following:<br><br>';
echo '$password_hash_from_db = trim($password_hash_from_db);<br>';
echo '$password_hash_from_db = substr($password_hash_from_db,1,60);<br>';
echo '$password_hash_from_db = str_replace(" ","",$password_hash_from_db);<br><br>';

$password_hash_from_db = trim($password_hash_from_db);
$password_hash_from_db = substr($password_hash_from_db,1,60);
$password_hash_from_db = str_replace(" ","",$password_hash_from_db);

if (password_verify ($user_password, $password_hash_from_db)) echo "password_verify()     from database hash = TRUE<br><br>";
else echo "password_verify() from database hash = FALSE<br><br>";

if (strlen($original_password_hash) === strlen($password_hash_from_db)) echo "hash     string lengths are EQUAL!<br>";
else "hash string lengths are NOT EQUAL<br>";

if ($original_password_hash === $password_hash_from_db) echo "hash strings DO match!    <br>";
else echo "hash strings DO NOT match!<br>";
%>

Если $storedPassword как вы и ожидаете - хеш, который совпадает с хэшем в поле пароля для пользователя, как определено в его электронной почте, - это должно означать, что пароль, который предоставляет пользователь, не совпадает с паролем в базе данных; так как это единственный логический вариант.

Я бы начал заново, и создал бы нового пользователя с новым паролем и посмотрел бы, работает ли он после этого. Пожалуйста, имейте в виду, что password поле в базе данных должно быть не менее 255 символов (varchar (255)) (возможно, ваше поле недостаточно велико, поэтому хранится только часть хеша - объясните вашу проблему).

Поэтому рекомендуется сохранять результат в столбце базы данных, который может расширяться за пределы 60 символов (255 символов будет хорошим выбором).

http://php.net/manual/en/function.password-hash.php

Другие вопросы по тегам