首页 > 解决方案 > 这是参数化查询的正确方法吗?还有其他方法吗?

问题描述

好吧,我学会了如何在 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');
        }
    }
}

我想知道它们是否比仅参数化查询更安全?

标签: phphtmlmysqlsql-injection

解决方案


您正在使用 INSERT 语句的参数,但您跳过了使用 SELECT 语句的参数。如果不对 SELECT 进行参数化,您仍然存在 SQL 注入漏洞。当您将不受信任的内容与 SQL 组合时,您需要在所有情况下都使用参数。

在将动态内容组合为 SQL 查询中的值时,参数是防止 SQL 注入的好方法。

你问是否有其他方法,所以如果你开始一个新的 PHP 项目,我会建议你使用PDO 。它比 Mysqli 简单一点。在我看来,没有理由使用 Mysqli,除非您要移植使用过时的 Mysql PHP 扩展的遗留 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 连接是以前建立的,并且它已启用 exceptions。如果你不启用异常,你应该检查每个的返回值prepare()execute()调用以确保没有错误。

Mysqli 也是如此,您可以启用异常,因此您不必手动检查错误。

我还在示例中显示了我更喜欢使用SELECT COUNT(*)而不是SELECT *. 在这种情况下,这可能是一个微不足道的优化,但如果*引用很多列或有很多行匹配username = $name,那么提取将需要从数据库中传输更少的数据。


推荐阅读