我学会了如何在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');
}
}
}
我想知道它们是否比仅参数化查询更为安全?
答案 0 :(得分:2)
您正在使用INSERT语句的参数,但是跳过了使用SELECT语句的参数。在不参数化SELECT的情况下,您仍然存在SQL注入漏洞。将不受信任的内容与SQL结合使用时,在所有情况下都需要使用参数。
参数是在将动态内容作为SQL查询中的值组合时防止SQL注入的好方法。
您询问是否还有其他方法,因此,如果您要开始一个新的PHP项目,我建议您使用PDO。比Mysqli容易一点。在我看来,除非您要移植使用过时的Mysql PHP扩展名的旧版PHP应用程序,否则没有理由使用Mysqli。
这是使用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连接是先前建立的,并且它是enabled with exceptions。如果不启用异常,则应检查每个prepare()
和execute()
调用中的返回值,以确保没有错误。
Mysqli也是一样,您可以enable exceptions,因此您不必手动检查错误。
我还在示例中显示了我偏爱使用SELECT COUNT(*)
而不是SELECT *
的情况。在这种情况下,这可能是微不足道的优化,但是如果*
引用了许多列或有许多行与username = $name
匹配,则提取操作将需要从数据库传输更少的数据。