Я хочу сравнить свой пароль и свой хеш-пароль с password_verify(), но всегда возвращает true. Почему это происходит?
Вот код:
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// username and password sent from form
$myusername = mysqli_real_escape_string($db,$_POST['username']);
$mypassword = mysqli_real_escape_string($db,$_POST['password']);
$hash = password_hash($mypassword, PASSWORD_DEFAULT);
$ourdb = "SELECT handle FROM qa_users WHERE handle = '$myusername' and passhash = '$mypassword'";
$ourresult = mysqli_query($db,$ourdb);
$ourrow = mysqli_fetch_array($ourresult,MYSQLI_ASSOC);
$ouractive = $ourrow['active'];
$ourcount = mysqli_num_rows($ourresult);
if (password_verify($mypassword, $hash)){
echo "hashed";
}
Почему нет должен возвращать true? Плюс: обязательное предупреждение «использовать подготовленные операторы».
откуда вы знаете/ожидаете, что это ложь?
Вы должны выбрать пароль из базы данных и сравнить его с введенным - вы сравниваете его с самим собой (эффективно).
Вы не должны использовать mysqli_real_escape_string в именах пользователей или паролях, потому что это может изменить их значение, в результате чего ваш пользователь не сможет войти в систему.
@GrumpyCrouton давно не виделись. Ваше утверждение справедливо только для пароля и только при правильном использовании хеширования. Принимая во внимание, что для присутствующего (недействительного) кода использование допустимо.
@YourCommonSense Верно, хотя обычно mysqli_real_escape_string вообще не требуется для любого значения при использовании подготовленных операторов. Клянусь, я видел случаи, когда mysqli_real_escape_string меняли чье-то имя пользователя, и они не могли войти на свой сайт. Кроме того, хеширование в коде OP кажется совершенно правильным, если они проверяют неправильно (конечно, их использование в настоящее время недействительно, на самом деле оно ничего не проверяет, оно фактически имеет 0 безопасности от простого входа в систему с любым паролем).
@GrumpyCrouton это может быть только в том случае, когда использование mres() совершенно неправильно, например, в дополнение к подготовленным операторам.
@YourCommonSense Тогда я согласен с вашим утверждением.






То, что вы сейчас делаете, это хешировать пароль (который вы экранировали первым; вы никогда не должны экранировать пароли, поскольку это изменяет хэш), а затем сопоставляете/проверяете его по сравнению со значением, которое вы только что хэшировали, без использования хэша из базы данных - так что это всегда будет соответствовать. Это эквивалент установки переменной $a = 'foo';, а затем проверки if ($a == 'foo') — проверка всегда будет возвращать значение true.
Вместо этого извлеките хешированное значение из базы данных на основе имени пользователя и используйте его в качестве второго аргумента для password_hash().
Также,
password_verify()query() и с использованием real_escape_string()) — см. Как я могу предотвратить внедрение SQL в PHP?if ($_SERVER["REQUEST_METHOD"] == "POST") {
$stmt = $db->prepare("SELECT passhash FROM qa_users WHERE handle = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$stmt->bind_result($hash);
$stmt->fetch();
if (password_verify($_POST['password'], $hash)) {
echo "Valid login";
} else {
echo "Invalid login";
}
$stmt->close();
}
Примечание для OP: использование заполнителя ? и bind_param() известно как использование подготовленных операторов, это эффективно устраняет риск SQL-инъекций, а также означает, что вам не нужно очищать свои входные данные перед их использованием в запросе.
@RaymondNijland Мало того, хеш для каждого хэша разный, поэтому вы не получите совпадений, даже если пароль на самом деле правильный. Но да, это тоже!
действительно, я знаю, что @Qirel password_hash() защищает от радужных таблиц, а использование blowfish также защищает от грубой силы GPU (кластеров). Поскольку blowfish не работает быстро на процессорах и очень медленно работает на GPU, если вы можете заставить его работать.
вы открыты для SQL-инъекций и должны немедленно решить