Это правильный способ параметризации запроса?Есть ли другой путь? - PullRequest
1 голос
/ 25 июня 2019

Что ж, я узнал, как параметризовать запросы в php, но я просто хотел спросить, теперь он полностью защищен от SQL-инъекций или любых других типов атак, и если это не так, что я могу сделать, чтобы защитить его еще больше?

<?php
include 'db.php';
$name = "";
$pass = "";
if(isset($_POST['send'])) {
    $name = $_POST['name'];
    $sql_u = "SELECT * FROM users WHERE username='$name'";
    $res_u = $connection->query($sql_u);
    if (mysqli_num_rows($res_u) > 0) {
        echo "Sorry Username already taken";
    }
    else {
        $password = $_POST['pass'];
        $hpass = password_hash($password, PASSWORD_DEFAULT);
        $query=$connection->prepare("insert into users (username,password) values (?,?)");
        $query->bind_param('ss',$name,$hpass);
        if ($query->execute()) {
            $query->close();
            header('location:index.php');
        } else {
            header('location:not.php');
        }
    }
}

Я хочу знать, является ли их еще более безопасный способ, чем только параметризация запросов?

1 Ответ

2 голосов
/ 25 июня 2019

Вы используете параметры для оператора INSERT, но вы пропустили использование параметров для оператора SELECT.Без параметризации SELECT у вас все еще есть уязвимость внедрения SQL.Необходимо использовать параметры во всех случаях, когда вы комбинируете ненадежный контент с вашим SQL.

Параметры - это хороший способ предотвратить внедрение SQL при объединении динамического контента в качестве значений в ваших запросах SQL.

Выспросил, есть ли другой способ, поэтому я рекомендую вам использовать PDO , если вы начинаете с новым проектом PHP.Это немного проще, чем Mysqli.На мой взгляд, нет причин использовать Mysqli, если вы не портируете устаревшее PHP-приложение, которое использовало устаревшее расширение Mysql PHP.

Вот как это будет выглядеть при использовании PDO:

$name = $_POST['name'];
$sql = "SELECT COUNT(*) FROM users WHERE username = ?";
$query = $connection->prepare($sql);
$query->execute([$name]);
$count = $query->fetchColumn();
if ($count > 0) {
    echo "Sorry Username already taken";
}
else {
    $password = $_POST['pass'];
    $hpass = password_hash($password, PASSWORD_DEFAULT);
    $sql = "insert into users (username, password) values (?, ?)";
    $query = $connection->prepare($sql);
    if ($query->execute([$name, $hpass])) {
        header('location:index.php');
    } else {
        header('location:not.php');
    }
}

Я предполагаю, что соединение PDO было установлено ранее, и было разрешено с исключениями .Если вы не включаете исключения, вы должны проверять возвращаемые значения при каждом вызове prepare() и execute(), чтобы убедиться в отсутствии ошибок.

То же самое верно для Mysqli, вы можете включить исключения , чтобы вам не приходилось проверять ошибки вручную.

Я также показываю в примере мое предпочтениеиспользуйте SELECT COUNT(*) вместо SELECT *.Это, вероятно, тривиальная оптимизация в этом случае, но если * относится ко многим столбцам или есть много строк, соответствующих username = $name, тогда при извлечении потребуется передать меньше данных из базы данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...