34

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

用使用 PDO 和实际准备好的语句的对象替换这些临时函数似乎很自然,但是在阅读了它们之后,我不太确定。PDO 似乎仍然是一个好主意,但准备好的语句的主要卖点之一是能够重用它们……我永远不会。这是我的设置:

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

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

编辑:

感谢所有好的建议,伙计们。这是我希望我可以将多个答案标记为“已接受”的地方——许多不同的观点。不过,最终,我必须对rick给予应有的回报……如果没有他的回答,即使听从了每个人的建议,我也会幸福地离开并做完全错误的事情。:-)

它是模拟的准备好的语句!

4

6 回答 6

25

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

于 2009-02-11T05:39:45.273 回答
18

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

于 2009-02-11T17:13:07.417 回答
15

什么时候使用准备好的语句?当您在数据库连接消失之前只运行一次语句时。

什么时候使用绑定查询参数(这实际上是大多数人使用准备好的语句来获取的)?我倾向于说“从不”,我真的很想说“从不”,但现实情况是大多数数据库和一些数据库抽象层在某些情况下不允许你绑定参数,所以你'被迫在这些情况下不使用它们。但是,任何其他时候,它都会使您的生活更简单,并且您的代码可以更安全地使用它们。

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

此外,如果您深入了解,大多数数据库抽象层都会准备查询,然后运行它,即使您只是告诉它执行静态 SQL 语句。因此,无论如何避免显式准备,您可能不会节省前往 db 的行程。

于 2009-02-11T17:39:20.410 回答
10

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

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

于 2009-02-11T09:58:19.113 回答
7

准备好的语句的好处如下:

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

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

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

于 2009-02-11T15:35:56.993 回答
2

老实说,我认为你不必担心。但是,我记得很多 PHP 数据访问框架都支持准备语句模式和非准备语句模式。如果我没记错的话,PEAR:DB 确实在当年。

我遇到了和你一样的问题,我有自己的保留意见,所以我最终没有使用 PDO,而是编写了自己的轻量级数据库层,它支持准备和标准语句,并在两者中执行正确的转义(防止 sql 注入)案例。我对 prepare 的其他抱怨之一是,有时将一些不可逃避的输入附加到诸如 ... WHERE id IN (1, 2, 3 ...) 之类的语句中会更有效。

我对 PDO 的了解还不够,无法告诉您使用它还有哪些其他选择。但是,我确实知道 PHP 具有可供它支持的所有数据库供应商使用的转义功能,并且您可以在您坚持使用的任何数据访问层之上滚动您自己的小层。

于 2009-02-11T09:12:00.487 回答