当*不*使用准备好的陈述?

时间:2009-02-11 04:47:11

标签: php mysql pdo prepared-statement

我正在重新设计一个使用最小数据库的PHP驱动的网站。原始版本使用“伪准备语句”(PHP函数进行引用和参数替换)来防止注入攻击并将数据库逻辑与页面逻辑分开。

用一个使用PDO和真实预处理语句的对象替换这些ad-hoc函数似乎很自然,但在阅读完它们之后,我不太确定。 PDO似乎仍然是一个好主意,但准备好的声明的主要卖点之一是能够重用它们......我永远不会。这是我的设置:

  • 这些陈述都非常简单。大多数都采用SELECT foo,bar FROM baz WHERE quux = ? ORDER BY bar LIMIT 1的形式。该批次中最复杂的陈述只是三个这样的选择与UNION ALL s。
  • 连接在一起
  • 每个页面点击执行最多一个语句并仅执行一次。
  • 我处于托管环境中,因此他个人通过任何“压力测试”来抨击他们的服务器。

鉴于使用准备好的语句至少会使我正在进行的数据库往返次数增加一倍,我最好避免使用它们吗?我是否可以使用PDO::MYSQL_ATTR_DIRECT_QUERY来避免多次数据库跳转的开销,同时保留参数化和注入防御的好处?或者,与执行我不应该担心的非准备查询相比,准备好的语句API使用的二进制调用是否运行得足够好?

修改

感谢所有好的建议,伙计们。这是我希望我可以将多个答案标记为“已接受”的地方 - 许多不同的观点。但最终,我必须给rick他应得的......如果没有他的回答,即使在跟随每个人的建议之后,我也会幸福地离开并完成错误的事情。 : - )

模仿准备好的陈述!

6 个答案:

答案 0 :(得分:26)

今天的软件工程规则:如果它不会为你做任何事情,请不要使用它。

答案 1 :(得分:17)

我想你想要PDO :: ATTR_EMULATE_PREPARES。这会关闭本机数据库预处理语句,但仍允许查询绑定以防止sql注入并保持sql整洁。据我所知,PDO :: MYSQL_ATTR_DIRECT_QUERY完全关闭了查询绑定。

答案 2 :(得分:15)

使用预准备语句时?当你只是在数据库连接消失之前运行语句一次。

使用绑定查询参数时(这实际上是大多数人使用预处理语句获取的)?我倾向于说“从不”,我真的想说“从不”,但实际情况是,大多数数据库和一些数据库抽象层在某些情况下都不允许你绑定参数,所以你在这种情况下,我们不得不使用它们。但是,在任何其他时间,它都会使您的生活更简单,并且您的代码使用起来更安全。

我不熟悉PDO,但我敢打赌它提供了一种机制,用于运行参数化查询,如果您不想准备,则使用相同函数调用中给出的值,然后作为单独的步骤运行。 (例如,像run_query("SELECT * FROM users WHERE id = ?", 1)或类似的东西。)

此外,如果你深入了解一下,大多数数据库抽象层都将准备查询,然后运行它,即使你只是告诉它执行一个静态SQL语句。因此,无论如何,你可能无法通过明确的准备来保存数据库之旅。

答案 3 :(得分:8)

准备好的声明正在被成千上万的人使用,因此经过充分测试(因此人们可以推断它们是相当安全的)。您的自定义解决方案仅供您使用。

您的自定义解决方案不安全的可能性非常高。使用预备陈述。你必须以这种方式维护更少的代码。

答案 4 :(得分:7)

准备好的陈述的好处如下:

  • 每个查询只编译一次
  • mysql将使用更高效的传输格式将数据发送到服务器

但是,准备好的语句仅在每个连接中保留。除非您使用连接池,否则如果您每页只执行一个语句,则没有任何好处。简单的简单查询也不会从更高效的传输格式中受益。

就个人而言,我不会打扰。伪准备语句可能对他们可能提供的安全变量引用有用。

答案 5 :(得分:2)

老实说,我认为你不应该担心它。但是,我记得许多PHP数据访问框架支持prepare语句模式和非prepare语句模式。如果我没记错的话,PEAR:DB当天回来了。

我遇到了和你一样的问题而且我有自己的保留意见,所以我没有使用PDO,而是编写了自己的轻量级数据库层,支持准备和标准语句,并执行了正确的转义(sql-injection prevention) )在这两种情况下。我准备的另一个抱怨是,有时将一些不可逃避的输入附加到像...... WHERE id IN(1,2,3 ......)这样的语句更有效。

我不太了解PDO告诉你使用它的其他选项。但是,我知道PHP已经为它支持的所有数据库供应商提供了转发函数,你可以在你遇到的任何数据访问层之上滚动你自己的小层。

相关问题