Реализация PDO в PHP

#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 Sense

5. В вашем старом коде никогда не было свойства password. В новом коде никогда не будет уведомления / предупреждения о том, что свойство не существует