简体   繁体   English

我们应该总是绑定我们的SQL语句吗?

[英]Should we always bind our SQL statements?

I have been researching into PDO's bindValue() . 我一直在研究PDO的bindValue() I know that preparing my SQL statements with PDO is keeping SQL injections from happening. 我知道用PDO准备我的SQL语句会阻止SQL注入的发生。

Code Example: 代码示例:

$stmt = $dbh->prepare('SELECT * FROM articles WHERE id = :id AND title = :title');
$stmt->bindValue(':id', PDO::PARAM_INT);
$stmt->bindValue(':title', PDO::PARAM_STR);
$stmt->execute();

By binding the ID as a number, and the Title was a string, we can limit the damage done when someone tries to do an SQL injection within the code. 通过将ID绑定为数字,并且Title是一个字符串,我们可以限制当有人尝试在代码中执行SQL注入时所造成的损害。

Should we always bind our values with a PDO::PARAM_ so we can limit what can be pulled from the database in an SQL injection? 我们是否应该始终将我们的值与PDO::PARAM_以便我们可以限制SQL注入中可以从数据库中提取的内容? Does this add more security with PDO when doing our bindValue() ? 在执行bindValue()时,这是否会增加PDO的安全性?

You should definitely use the prepare API and pass values separately from the query, as opposed to doing plain string interpolation (eg "SELECT * FROM foo WHERE bar = '$baz'"bad ). 你应该使用prepare API并从查询中单独传递值, 而不是进行普通的字符串插值 (例如"SELECT * FROM foo WHERE bar = '$baz'"bad )。

For binding parameters, you have three options: 对于绑定参数,您有三个选项:

It doesn't really matter which of these you use, they're all equally secure. 你使用它们中的哪一个并不重要,它们都同样安全。 See these answers for some details about the differences: 有关差异的一些详细信息,请参阅以下答案:

When using bindParam or bindValue , passing the third PDO::PARAM_ argument type is optional. 使用bindParambindValue ,传递第三个PDO::PARAM_参数类型是可选的。 If you don't pass it, it defaults to binding the argument as string. 如果未传递,则默认将参数绑定为字符串。 That means you may end up with a query equivalent to ... WHERE foo = '42' instead of ... WHERE foo = 42 . 这意味着你最终可能得到一个等于... WHERE foo = '42'而不是... WHERE foo = 42 It depends on your database how it will handle this. 这取决于您的数据库如何处理它。 MySQL will cast the string to a number automatically as needed, just as PHP does (eg in '42' + 1 ). MySQL会根据需要自动将字符串转换为数字,就像PHP一样(例如在'42' + 1 )。 Other databases may be more fussy about types. 其他数据库可能对类型更加挑剔。

Again, all options are equally safe. 同样,所有选项都同样安全。 If you're trying to bind a string 'foo' using PDO::PARAM_INT , the string will be cast to an integer and accordingly bound as the value 0 . 如果您尝试使用PDO::PARAM_INT绑定字符串'foo' ,则字符串将PDO::PARAM_INT转换为整数,并因此绑定为值0 There's no possibility for injection. 注射不可能。

There are two questions in one. 一个问题有两个。 It is essential not to confuse them 至关重要的是不要混淆它们

  1. Should we always use a placeholder to represent a variable data in the query? 我们是否应始终使用占位符来表示查询中的变量数据?
  2. Should we always use certain function in the application code to follow the above rule? 我们是否应该始终在应用程序代码中使用某些功能来遵循上述规则?
    Also, from the clarification in the comments under the opening post , the third question can be seen: 此外, 根据开幕式下评论澄清,可以看到第三个问题:
  3. Should we always use third parameter, or it's OK to let PDO bind all the parameters as strings by default? 我们应该总是使用第三个参数,还是可以让PDO默认将所有参数绑定为字符串?

1. For the first question the answer is absolutely and definitely - YES. 1.对于第一个问题,答案是绝对肯定的 - 是的。

While for the second one, for sake of code sanity and DRYness - 而对于第二个,为了代码的健全和干燥 -

2. Avoid manual binding when possible. 2.尽可能避免手动绑定。

There are many ways to avoid manual binding. 有许多方法可以避免手动绑定。 Some of them are: 他们之中有一些是:

  • ORM is an excellent solution for the simple CRUD operations and must have in a modern app. ORM是简单CRUD操作的绝佳解决方案,必须在现代应用程序中使用。 It will hide SQL from you completely, doing the binding behind the scenes: 它将完全隐藏SQL,在幕后进行绑定:

     $user = User::model()->findByPk($id); 
  • Query Builder is also the way to go, disguising SQL in some PHP operators but again hiding the binding behind the scenes: 查询生成器也是一种方法,在一些PHP运算符中伪装SQL,但再次隐藏在幕后的绑定:

     $user = $db->select('*')->from('users')->where('id = ?', $id)->fetch(); 
  • some abstraction library may take care of the passed data by means of type-hinted-placeholders , hiding the actual binding again: 一些抽象库可以通过类型提示占位符来处理传递的数据,再次隐藏实际的绑定:

     $user = $db->getRow("SELECT * FROM users WHERE id =?i", $id); 
  • if you are still using PHP in the last century ways, and have raw PDO all over the code - then you can pass your variables in execute(), still saving yourself a lot of typing: 如果你仍然在上个世纪的方式使用PHP,并且在整个代码中都有原始的PDO - 那么你可以在execute()中传递你的变量,仍然可以节省很多自己的输入:

     $stmt = $dbh->prepare('SELECT * FROM users WHERE id = ?'); $stmt->execute([$id]); $user = $stmt->fetch(); 

As of the third question - as long as you are binding numbers as strings (but not the opposite!) - 从第三个问题开始 - 只要你将数字绑定为字符串(但不是相反!) -

3. It's all right with mysql, to send almost every parameter as a string 3.使用mysql可以将几乎所有参数作为字符串发送

as mysql will always convert your data to the proper type. 因为mysql总是将您的数据转换为正确的类型。 The only case known to me, is a LIMIT clause where you cannot format number as a string - thus, the only related case is one when PDO is set in emulation mode and you have to pass a parameter in LIMIT clause . 我知道的唯一情况是LIMIT子句,您不能将数字格式化为字符串 - 因此,唯一相关的情况是在仿真模式下设置PDO并且您必须在LIMIT子句中传递参数时 In all other cases you can omit third parameter, as well as explicit call to bindValue() without any problem. 在所有其他情况下,您可以省略第三个参数,以及显式调用bindValue()而没有任何问题。

Yes you should always bind params with prepared statement. 是的,你应该总是用准备好的声明绑定params。 It's more secure, and limit SQL injection. 它更安全,并限制SQL注入。 But this is not the only think you must do to query params: a correct type control is required, best if you map a row into an object and throw an exception in it if it has invalid data. 但这不是你必须要做的唯一一个查询params的方法:需要一个正确的类型控件,最好是将一行映射到一个对象中,如果它有无效数据则抛出异常。

I hope I can be useful! 我希望我能有用!

Yes , binding is the way to go. 是的 ,绑定是要走的路。 Or parameterised queries which a more generalized term. 或参数化查询哪个更通用的术语。

@Theo does a wonderful job explaining why parameterized queries is the way to go @Theo做了很好的工作,解释了参数化查询为什么要走的路

You could also use stored procedures for additional security but is an over kill if you have one application to one database. 您还可以使用存储过程来获得额外的安全性,但如果您有一个应用程序到一个数据库,则会过度使用。 Its good for multiple applications to one database to ensure consistency when handling data 它适用于一个数据库的多个应用程序,以确保处理数据时的一致性

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

相关问题 我们应该始终在MySQL和php中使用准备好的语句还是何时使用这些语句? - Should we always use prepared statements in MySQL and php or when to use these? 我们应该使用Pylons或PHP作为我们的webapp吗? - Should we use Pylons or PHP for our webapp? 如果我们在程序中使用延迟,我们应该使用cron吗? - should we use cron if we are using delay in our program…? 我们是否总是在“ IF”语句中测试“ AND”和“ OR”的两个成员? - Do we always test the two members of “AND” and “OR” in “IF” statements? 如果还要使用其他语句? - How many else if statements should we use? 我们应该始终跟踪查询和数据库错误吗? - Should we always track query and db errors? 总是用 PHP 准备 SQL 语句是否有任何问题? - Are there any issues with always preparing SQL statements with PHP? Doctrine2 ORM是否总是准备语句? 我应该始终在DBAL中使用准备好的语句吗? - Does Doctrine2 ORM always prepare the statements? Should I always use prepared statements with DBAL? 在 php bind_param function 中插入 SQL 语句 - Insert SQL statements in php bind_param function 使用 bitnami wapp 时,我们应该将 html 和 php 文件保存在哪里? - Where should we save our html and php files while using bitnami wapp?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM