php - 了解 PDO 准备语句和绑定(bind)参数

标签 php mysql pdo prepare bindparam

根据经验,并且不断被告知使用准备好的语句和绑定(bind)参数的好处,我经常在代码中使用这两种技术,但是我想确切地了解这两种技术的用途:

根据我对准备好的语句的理解:

$sql = "SELECT * FROM myTable WHERE id = ".$id;
$stmt = $conn->prepare($sql);
$stmt->execute();

前面的代码应该使用我建议的查询在数据库中创建一种缓冲区。现在根据我的理解(我可能是非常错误的),之前的代码是不安全的,因为字符串 $sql 可以是任何内容,具体取决于 $id 实际上是,并且 if $id = 1; DROP TABLE myTable;--,即使我有准备好的语句,我也会插入恶意查询。

根据我的理解,这是绑定(bind)我的参数的地方。如果我执行以下操作:

$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();

数据库应该事先准确地知道sql语句的所有部分: SELECT 这些列:* FROM myTableWHERE id = “用户输入的变量”,如果“用户输入的变量”!=变量,则查询失败。

有人告诉我我的理解是正确的,而另一些人则告诉我这是错误的,有人可以让我知道我是否错误、正确或遗漏了什么吗?并根据您的需要进行详细说明,非常感谢所有反馈!

最佳答案

你是对的,第一种情况是不安全的。不过,重要的是要理解,只有在使用变量数据和/或重复执行相同的查询时,准备语句才有值(value)。如果您正在执行没有变量的简单语句,您可以简单地执行以下操作:

$sql = "SELECT * from myTable WHERE this_column IS NOT NULL";
$result = $conn->query($sql);

最终得到一个可使用的 PDOStatement 对象,就像使用 PDO::exec() 时一样。

对于你的第二种情况,同样,你基本上是正确的。发生的情况是传递给数据库的变量被转义并加引号(除非您使用 PDOStatement::bindParam() 的第三个参数另外指定,否则它将作为字符串发送,这在大多数情况下都可以。)因此,如果发送错误数据,查询不会“失败”。它的行为就像您传递了一个数据库中不存在的有效数字一样。当然还有some edge cases即使有正确准备的声明,您仍然很容易受到攻击。

此外,为了让生活更轻松,您可以使用这样的准备好的语句来进行隐式绑定(bind):

$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->execute([":id"=>$id]);

或者甚至像这样,使用未命名的参数:

$sql = "SELECT * FROM myTable WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->execute([$id]);

当然,大部分内容已经在我输入答案时在评论中进行了解释!

关于php - 了解 PDO 准备语句和绑定(bind)参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37123568/

相关文章:

php - 按相对路径包含文件

php - 取决于项目查询的意外项目评论

PHP PDO : WHy doesn't work my code to insert multiple rows with different values?

php - 流明:异常处理程序 - 不捕获 QueryException 或 PDOException

php - 使用 SQL 查询访问表时遇到问题。没有得到想要的结果

MySQL 跨表删除

java - 如何修复 com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException : No operations allowed after connection closed. 异常?

php - PDO Bind Params 取决于它们是否存在于查询中

PHP PDO 上一个函数的lastinsertid

javascript - 如何重定向页面