我正在重新设计一个使用最小数据库的 PHP 驱动的网站。原始版本使用“伪准备语句”(进行引用和参数替换的 PHP 函数)来防止注入攻击并将数据库逻辑与页面逻辑分开。
用使用 PDO 和真正准备好的语句的对象替换这些临时函数似乎很自然,但在阅读它们之后,我不太确定。 PDO 看起来仍然是一个好主意,但准备好的语句的主要卖点之一是能够重用它们……我永远不会。这是我的设置:
SELECT foo,bar FROM baz WHERE quux = ? ORDER BY bar LIMIT 1
的形式。其中最复杂的语句就是三个这样的选择用 UNION ALL
连接在一起。PDO::MYSQL_ATTR_DIRECT_QUERY
来避免多次数据库访问的开销,同时保留参数化和注入防御的好处吗?或者,与执行非准备好的查询相比,准备好的语句 API 使用的二进制调用是否表现得足够好,我不应该担心?
当今的软件工程规则:如果它不能为你做任何事,就不要使用它。
不使用准备好的语句? 当您只想在数据库连接消失之前运行该语句一次时。
何时不使用绑定查询参数(这实际上是大多数人使用准备好的语句来获取的)? 我倾向于说“从不”,而且我真的很想说“从不”,但现实是大多数数据库和一些数据库抽象层在某些情况下不允许您绑定参数,因此您在这些情况下被迫不使用它们。 但在任何其他时候,它都会让您的生活变得更简单,并且您的代码使用它们会更安全。
我不熟悉 PDO,但我敢打赌它提供了一种机制,如果您不想准备,则可以使用同一函数调用中给出的值运行参数化查询,然后作为单独的步骤运行。 (例如,类似run_query("SELECT * FROM users WHERE id = ?", 1)
或类似内容。)此外,如果您深入了解,大多数数据库抽象层都会准备查询,然后运行它,即使您只是告诉它执行静态 SQL 语句。 因此,无论如何,您可能都不会通过避免显式准备来节省数据库之旅。
您的自定义解决方案不安全的可能性非常高。使用准备好的语句。这样你就必须维护更少的代码。
就我个人而言,我不会打扰。伪准备语句可能对于它们可能提供的安全变量引用很有用。
我遇到了和你一样的问题,我也有自己的保留,所以我最终没有使用 PDO,而是编写了自己的轻量级数据库层,该数据库层支持准备和标准语句,并在中执行正确的转义(sql 注入预防)两种情况。我对准备的另一个抱怨是,有时将一些不可转义的输入附加到诸如 ... WHERE id IN (1, 2, 3...) 之类的语句中会更有效。
我对 PDO 的了解还不够,无法告诉您使用它还有哪些其他选项。然而,我确实知道 PHP 具有可用于它支持的所有数据库供应商的转义函数,并且您可以在您所坚持的任何数据访问层之上滚动您自己的小层。