Php 何时*不*使用准备好的语句?
我正在重新设计一个使用最小数据库的PHP驱动的网站。原始版本使用“伪准备语句”(进行引用和参数替换的PHP函数)来防止注入攻击,并将数据库逻辑与页面逻辑分离 用一个使用PDO和real prepared语句的对象替换这些特殊函数似乎很自然,但在阅读了它们之后,我不太确定。PDO似乎仍然是一个好主意,但预处理语句的主要卖点之一是能够重用它们……我永远不会这样做。以下是我的设置:Php 何时*不*使用准备好的语句?,php,mysql,pdo,prepared-statement,Php,Mysql,Pdo,Prepared Statement,我正在重新设计一个使用最小数据库的PHP驱动的网站。原始版本使用“伪准备语句”(进行引用和参数替换的PHP函数)来防止注入攻击,并将数据库逻辑与页面逻辑分离 用一个使用PDO和real prepared语句的对象替换这些特殊函数似乎很自然,但在阅读了它们之后,我不太确定。PDO似乎仍然是一个好主意,但预处理语句的主要卖点之一是能够重用它们……我永远不会这样做。以下是我的设置: 这些陈述都非常简单。大多数都是selectfoo,bar frombaz,其中qux=?按条订购限制1。该批次中最复杂
- 这些陈述都非常简单。大多数都是
。该批次中最复杂的语句就是三个这样的选择与selectfoo,bar frombaz,其中qux=?按条订购限制1
s连接在一起UNION ALL
- 每个页面命中最多执行一条语句,并且只执行一次
- 我在一个托管环境中,因此对通过亲自进行任何“压力测试”来关闭他们的服务器持谨慎态度
PDO::MYSQL\u ATTR\u DIRECT\u QUERY
来避免多次数据库访问的开销,同时保留参数化和注入防御的好处吗?或者,与执行我不必担心的未准备好的查询相比,准备好的语句API使用的二进制调用的性能是否足够好
编辑:
谢谢你们的建议,伙计们。这是一个我希望我可以标记多个答案为“接受”-许多不同的观点。不过,最终,我不得不给他应得的……如果没有他的回答,我会很高兴地离开,做了一件完全错误的事情,即使是在听从了所有人的建议之后。:-)
模拟准备好的声明,它是 今天的软件工程规则:如果它对你没有任何帮助,就不要使用它。老实说,我认为你不应该担心它。然而,我记得许多PHP数据访问框架支持prepare语句模式和non-prepare语句模式。如果我没记错的话,PEAR:DB在那一天做过 我遇到了与您相同的问题,我也有自己的保留意见,因此我没有使用PDO,而是编写了自己的轻量级数据库层,它支持prepares和标准语句,并在这两种情况下执行正确的转义(sql注入预防)。我对prepares的另一个不满是,有时将一些不可转义的输入附加到一个语句(如。。。其中id位于(1、2、3…)
我对PDO的了解还不够,无法告诉您使用它还有哪些其他选择。然而,我确实知道PHP为它支持的所有数据库供应商提供了转义功能,您可以将自己的小层放在任何数据访问层之上。准备好的语句被成千上万的人使用,因此经过了很好的测试(因此可以推断它们是相当安全的)。您的自定义解决方案仅由您使用
您的自定义解决方案不安全的可能性非常高。使用事先准备好的陈述。这样,您必须维护更少的代码。准备好的语句的好处如下:
- 每个查询只编译一次
- mysql将使用更高效的传输格式向服务器发送数据
就我个人而言,我不想麻烦。伪准备语句可能对引用它们可能提供的安全变量很有用。我认为您需要PDO::ATTR_EMULATE_PREPARES。这将关闭本机数据库准备语句,但仍然允许查询绑定来防止sql注入并保持sql整洁。据我所知,PDO::MYSQL\u ATTR\u DIRECT\u QUERY完全关闭查询绑定。什么时候不使用准备好的语句?在db连接断开之前只运行一次语句 什么时候不使用绑定查询参数(这是大多数人使用预处理语句得到的)?我倾向于说“从不”,我真的很想说“从不”,但事实是,大多数数据库和一些db抽象层都有某些特定的情况,在这些情况下,它们不允许您绑定参数,因此在这些情况下,您不得不不使用它们。不过,在其他任何时候,使用它们都会使您的生活更简单,代码更安全 我不熟悉PDO,但我敢打赌它提供了一种机制,可以使用同一个函数调用中给定的值运行参数化查询,如果您不想准备,那么可以作为单独的步骤运行。(例如,类似于
run_query(“SELECT*FROM users,其中id=?”,1)
或类似的内容。)
此外,如果您仔细观察,大多数db抽象层将准备查询,然后运行它,即使您只是告诉它执行静态SQL语句。因此,不管怎样,您可能没有通过避免显式准备来节省到数据库的行程。您错过了一个:智能地引用传递给它的数据。错过了一个,但不是那个。准备好的语句的参数通过一个单独的通道传递给db服务器(即,不作为SQL语句的一部分),因此它们根本不需要转义,因为它们明确地以数据的形式传入,而不是作为一个潜在的命令。这不会改变任何效率,或者更糟。SQL是在服务器上编译的,而不是在客户端。因此,当您发送一个带有绑定参数的准备好的语句时,您实际上向服务器发送了多个数据包(一个用于t