【发布时间】:2020-08-20 07:38:08
【问题描述】:
既然所有 SQL 查询都应该准备好以防止 SQL 注入,为什么我们允许编写和执行非准备好的查询?这看起来是不是违反直觉?
【问题讨论】:
标签: mysql sql sql-injection
既然所有 SQL 查询都应该准备好以防止 SQL 注入,为什么我们允许编写和执行非准备好的查询?这看起来是不是违反直觉?
【问题讨论】:
标签: mysql sql sql-injection
如果查询是固定字符串并且不需要任何程序变量,则使用query() 运行它是安全的。
这是来自https://www.php.net/manual/en/pdo.query.php的示例:
<?php
$sql = 'SELECT name, color, calories FROM fruit ORDER BY name';
foreach ($conn->query($sql) as $row) {
print $row['name'] . "\t";
print $row['color'] . "\t";
print $row['calories'] . "\n";
}
查询中没有 PHP 变量。 query() 就足够了,完成与prepare() 和execute() 相同。
如果您需要用 PHP 变量替换 SQL 表达式中的值,那么您可以使用参数:
$sql = 'SELECT name, colour, calories FROM fruit
WHERE calories < :calories AND colour = :colour';
$sth = $dbh->prepare($sql);
$sth->execute(array('calories' => 150, 'colour' => 'red'));
您可能会发现这在您的应用程序中比运行固定查询更常见。
【讨论】:
prepare,有时使用字符串连接会很麻烦,所以有一个论点,你最好总是使用prepare,除非你有充分的理由不这样做。
即使您需要使用准备好的语句,也无法阻止通过变量替换创建准备好的语句。例如
$sql = "SELECT * FROM someTable WHERE id = $id";
$stmt = $conn->prepare($sql);
【讨论】:
绑定参数和query preparation 是两个不同的东西。你可以做一个或另一个或两者兼而有之。
您需要绑定参数以防止 SQL 注入。但是,有些东西不能作为参数传递(例如 ORDER BY 列表),在这种情况下,您可以将所需的 SQL 语法直接连接到 SQL 字符串中。这称为“动态 SQL”,通常应仅使用列入白名单的字符串来防止 SQL 注入。
所以回答(我认为是)您的问题:允许使用动态 SQL,因为绑定参数未涵盖某些情况。
【讨论】:
prepare()就不能使用绑定参数。
DbCommand.Prepare 的情况下绑定参数,或者至少它在 Oracle 和 MS SQL Server 上是这样工作的。对 ODBC 也是如此。自从我上次尝试使用 MySQL 以来已经有很长时间了,如果我错了,请纠正我......
query(),那么它没有执行绑定参数。