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 символов будет хорошим выбором).