#php #pdo
#php #pdo
Вопрос:
Я адаптировал старый PHP-код, потому что в нем не было никакой безопасности. По общему признанию, я неопытен, когда речь идет о синтаксисе PDO. Поэтому мне, вероятно, нужно изменить некоторые из более поздних инструкций. Я смог хэшировать и солить пароли и смог заставить работать функцию проверки пароля. Затем я начал включать подготовленную инструкцию, но столкнулся с трудностями. Функция ISSET правильно определяет отсутствующие поля. Однако, когда я выполняю инструкцию, я получаю пустую страницу. Так что не нужно пропускать сообщения об ошибках. Даже когда я жестко прописываю имя пользователя администратора в инструкции SQL, пароль не проверяется функцией password_verify . Также не назначается какая-либо роль сеанса. Так что даже когда вы попадаете на страницу администратора. Вам скажут, что у вас нет нужных пользовательских привилегий для доступа к нему.
<?php
// start session
session_start();
?>
<html>
<body>
<?php
// Import the credentials
include 'dbinfo.php';
try
{
$conn = new PDO("mysql:host=$servername; dbname=$dbname", $dbusername, $dbpassword);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if(isset($_POST["login"]))
{
if(empty($_POST["username"]) || empty($_POST["password"]))
{
echo "all fields required";
}
else
{
$statement = $conn->prepare("SELECT * FROM users WHERE username = :username");
$statement->execute();
$row = $statement->fetch();
(
array
(
'username' => $_POST["username"]
//'password' => $_POST["password"]
)
);
if(password_verify($_POST['password'], $password))
{
echo "valid";
}
else
{
echo "not valid";
}
$count = $statement->rowCount();
if($count > 0)
{
$row = mysqli_fetch_assoc($result);
$role = $row['role'];
//set session variable
$_SESSION['role'] = $role;
// echo "Successful login!";
//redirect
header("Location: AdminEdit.html");
}
else
{
echo "Record not found <br />";
echo "<a href='Admin.html'>Back to login page</a>";
}
}
}
}
catch(PDOException $error)
{
$message = $error->getMessage();
}
?>
</body>
</html>
Комментарии:
1. Действительно ли ваш PHP-код находится внутри HTML?
2. Удалите это
try-catch
из своего кода. Это плохая практика, и она вам вообще не нужна3. ` $statement->execute();` должен иметь массив в качестве аргумента. Вы ничего не предоставили.
4.
$count = $statement->rowCount(); if($count > 0)
совершенно бесполезно и избыточно. Уберите его.5. Также проверьте это, чтобы перейти к адаптации. Содержит очень полезную информацию о PDO.
Ответ №1:
Вам нужно передать параметры, которые вы привязываете к своему запросу, в ваш execute
оператор, возвращаемый из prepare
метода.
Вы также должны убедиться, что имя пользователя / пароль не являются пустыми. Это можно сделать с помощью array_diff
array_keys
, а не вручную, построчной проверки или цикла.
if(array_diff(['username', 'password'], array_keys($_POST)))
{
# TODO: Create this exception to trigger a HTML response view
throw SomeRequiredArgException;
}
$stmt = $conn->prepare('SELECT * FROM users WHERE username = ?');
$stmt->execute([$_POST['username']]);
# fetch the record the usual way
$record = $stmt->fetch(PDO::FETCH_OBJ);
# check whether a record exists and password is correct in one go
if($record amp;amp; password_verify($_POST['password'], $record->password)) {
# Successful login attempt
# TODO: Set your session correctly as stated at the bottom of this answer.
} else {
# TODO: send back a wrong credentials message to a user;
}
На будущее обратите внимание: я бы не стал устанавливать значение сеанса, которое повышает доступ к вашему приложению, как что-то вроде роли. Я бы использовал носитель (JWT). В противном случае я бы создал IV следующим образом.
# IV
bin2hex(random_bytes(32));
Комментарии:
1. Спасибо, теперь мне просто нужно выяснить, как адаптировать объявленный сеанс к PDO.
2. Прямо сейчас этот код не имеет смысла, поскольку имя пользователя не является массивом. Я упрощу это для вас
3. Кроме того, неправильные учетные данные не являются исключительной ситуацией, а скорее ожидаемым поведением.
4. Затем, когда
fetch
возвращает значение empty и OP пытается запуститьpassword_verify
$record->password
и получает исключение / предупреждение о том, что свойствоpassword
не существует, что тогда? Кроме того, неправильные учетные данные не соответствуют правилу в этом контексте, поэтому их можно рассматривать как исключение, так в чем же ваша странная проблема? @YOURCOMMON Sense5. В вашем старом коде никогда не было свойства password. В новом коде никогда не будет уведомления / предупреждения о том, что свойство не существует