简体   繁体   English

了解PDO准备的语句和绑定参数

[英]Understanding PDO Prepared Statements and Binding Parameters

From experience and also having been told constantly the benefits of using prepared statements and binding my parameters, I have constantly used those two techniques in my code, however I would like to understand exactly the purpose of each of those two techiques: 根据经验,并不断被告知使用准备好的语句和绑定参数的好处,我在代码中不断使用了这两种技术,但是我想确切地了解这两种技术的目的:

From my understanding of prepared statements: 根据我对准备好的陈述的理解:

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

The previous code should create a sort of a buffer in the database with the query I proposed. 前面的代码应该使用我建议的查询在数据库中创建某种缓冲区。 Now FROM MY UNDERSTANDING (and I could be very wrong), the previous code is insecure, because the string $sql could be anything depending on what $id actually is, and if $id = 1; DROP TABLE myTable;-- 现在从我的理解 (我可能是非常错误的)开始,前面的代码是不安全的,因为字符串$sql可以取决于$id实际含义,如果$id = 1; DROP TABLE myTable;-- 1; DROP TABLE myTable;-- , I would be inserting a malicious query even though I have a prepared statement. 1; DROP TABLE myTable;--即使我有一个准备好的语句,我也会插入一个恶意查询。

FROM MY UNDERSTANDING this is where binding my parameters com in. If I do the following instead: 从我的理解,这是绑定参数com的地方。如果我执行以下操作,则:

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

The database should know exactly all the parts of the sql statement before hand: SELECT these columns: * FROM myTable and WHERE id = "a variable that was input by the user", and if "a variable that was input by the user" != a variable , the query fails. 数据库应该事先确切知道sql语句的所有部分: SELECT这些列: * FROM myTableWHERE id = “一个用户输入的变量”,如果是"a variable that was input by the user" != a variable ,查询失败。

I have been told by some my understanding is correct, and by others that it is false, could someone please let me know if I am wrong, correct, or missing something? 有人告诉我我的理解是正确的,而有人告诉我我的理解是错误的,有人可以让我知道我是错的,正确的还是遗漏了什么吗? And elaborate as much as you want, all feedback is greatly appreciated! 并根据您的需要精心制作,非常感谢所有反馈!

You're correct that the first case is insecure. 您是正确的,第一种情况是不安全的。 It's important to understand though, that preparing a statement only has value if you are using variable data, and/or executing the same query repeatedly. 不过,重要的是要理解,只有在使用变量数据和/或重复执行相同的查询时,准备语句才有价值。 If you are executing plain statements with no variables , you could simply do this: 如果要执行不带变量的普通语句,则只需执行以下操作:

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

And end up with a PDOStatement object to work with, just like when you use PDO::exec() . 并最终使用一个PDOStatement对象,就像使用PDO::exec()

For your second case, again, you're largely correct. 同样,对于第二种情况,您基本上是正确的。 What's happening is the variable passed to the database is escaped and quoted (unless you specify otherwise with the third argument to PDOStatement::bindParam() , it's sent as a string which is fine for most cases.) So, the query won't "fail" if bad data is sent. 发生的情况是传递给数据库的变量被转义并加引号(除非您另外使用PDOStatement::bindParam()的第三个参数指定,否则它将作为字符串发送,这在大多数情况下都可以使用。)因此,查询不会如果发送了错误的数据,则为“失败”。 It behaves exactly as if you had passed a valid number that didn't exist as an ID in the database. 它的行为就好像您传递了一个有效的数字一样,该数字在数据库中作为ID不存在。 There are, of course, some edge cases where you are still vulnerable even with a correctly prepared statement. 当然,在某些极端情况下 ,即使使用正确准备的语句,您仍然容易受到攻击。

Also, to make life easier, you can use prepared statements like this, to do implicit binding: 另外,为使生活更轻松,您可以使用如下准备的语句进行隐式绑定:

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

Or even like this, with un-named parameters: 甚至像这样,使用未命名的参数:

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

Naturally, most of this has been explained in the comments while I was typing up the answer! 自然,大多数情况已经在我输入答案时在注释中解释了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM