【问题标题】:prepared statements - are they necessary准备好的陈述 - 它们是否必要
【发布时间】:2011-09-11 19:24:23
【问题描述】:

准备好的语句添加了大量的代码……但我不断听到有人提到使用它们……从 1 行代码到大约 6 行代码增加了什么价值?这仅仅是为了防止sql注入吗?

类似的帖子here。

php.net 关于准备好的语句here

【问题讨论】:

  • 你可以将这 6 行代码包装成一个方法,也只有一行。
  • 这个问题之前已经讨论过,但是我很难找到合适的重复链接:(
  • 我链接到上面的一个,说明您不需要将 mysqli_real_escape_string() 与准备好的查询一起使用。这很好。我的服务器提供商将魔术引号设置为错误的值...这意味着我需要大量代码才能使用该特定功能...
  • 说从常规语句到准备好的语句是以增加 5 行代码为代价的,这是不公平的。首先,如果整体代码更具可读性和安全性,额外的代码不一定是坏事。此外,您在示例中使用的许多行要么是常规语句所必需的,要么与准备好的语句完全无关。

标签: php mysqli


【解决方案1】:

Prepared statements 提供了出色的 SQL 注入保护。

除了 SQL 注入保护之外,当同一个查询要多次执行时(例如在 INSERT 循环中),准备好的语句可以减少数据库服务器上的负载。该语句仅由 RDBMS 编译一次,而不像在 mysql_query() 调用中那样每次都需要编译。

不同的 API 需要不同数量的代码来执行准备好的语句。我发现 PDO 可以比 MySQLi 稍微简洁一些,例如,如果您的情况允许在 execute() 调用中使用隐式参数绑定。这只有在你所有的参数都可以被评估为字符串的情况下才有效。

// PDO implicit binding example:
// Not many lines of code if the situation allows for it
$stmt = $pdo->prepare("SELECT * FROM tbl WHERE col1=? AND col2=? AND col3=?");
$stmt->execute(array($val1, $val2, $val3));

【讨论】:

  • mysql_query 的这个比较...与 mysqli_query() 的比较...我几周前才更新到这个...现在我要再次更新了。
  • @Chris 是的,同样的比较也适用于mysqli_query()。必须在 RDBMS 每次调用时编译语句
  • 正确但甚至错误:准备好的语句不提供任何“保护”。它只是提供某种保护的参数绑定接口。但是准备好的语句是错误的工具!在许多情况下,准备好的语句甚至是糟糕的。性能方面和资源方面。我不明白 PDO 开发人员没有纠正他们的误解。它令人困惑。
【解决方案2】:

说prepared statements 导致1 行代码爆炸到6 行是不公平的。实际上,要使用一个,您只需要2 行:一个用于准备语句,一个用于绑定参数。即使您没有使用准备好的语句,也需要您编写的任何其他代码(执行查询、绑定结果、获取结果等)。

所以本质上我们是在讨论一个额外的代码行给你带来了什么。它给你带来了两件事:

  1. 防止 sql 注入(其中还包括防止非恶意格式错误的查询,例如,如果注入的变量包含单引号,则防止查询中断)
  2. 如果您最终为不同的注入值执行相同的预处理语句,可能会带来性能优势。

第 2 点可能并不总是适用,但请考虑第 1 点也为您省去了手动转义要在查询中注入的值的必要麻烦。如果不使用准备好的语句,这将是您需要自己编写的额外代码(即使您可以在同一行内联)。

在我看来,我们可以得出结论,通过准备好的语句,您最终会免费获得性能和性能。

【讨论】:

  • 我认为您获得了安全性和可读性..但如果它只是一个查询而不是一个循环...我认为它们的性能下降非常小...每一个以上的好处来时你多次调用它......
  • @ChrisAaker:最初您担心编写不必要的代码(我认为这在实践中最终不会发生),所以我没有解决性能问题。至于后者,恕我直言,性能与安全性是完全错误的看待事物的方式,除非您拥有 Facebook 的流量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-19
  • 2013-06-09
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
相关资源
最近更新 更多