我正在重新设计一个使用最小数据库的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他应得的......如果没有他的答案,我会幸福地离开并完成错误的事情,即使遵循了所有人的建议.:-)
仿真准备好的陈述吧!
今天的软件工程规则:如果它不会为你做任何事情,请不要使用它.
我想你想要PDO :: ATTR_EMULATE_PREPARES.这会关闭本机数据库预处理语句,但仍允许查询绑定以防止sql注入并保持sql整洁.据我所知,PDO :: MYSQL_ATTR_DIRECT_QUERY完全关闭了查询绑定.
何时不使用准备好的陈述?在数据库连接消失之前,您只需要运行一次语句.
何时不使用绑定查询参数(这实际上是大多数人使用预处理语句获取的)?我倾向于说"从不",我真的想说"从不",但实际情况是,大多数数据库和一些数据库抽象层在某些情况下都不允许你绑定参数,所以你在这种情况下,我们不得不使用它们.但是,任何时候,它都会让您的生活变得更简单,并且您的代码使用起来更安全.
我不熟悉PDO,但我敢打赌它提供了一种机制,用于运行参数化查询,如果您不想准备,则使用相同函数调用中给出的值,然后作为单独的步骤运行.(例如,类似run_query("SELECT * FROM users WHERE id = ?", 1)
或类似的东西.)
此外,如果你深入了解,大多数数据库抽象层将准备查询,然后运行它,即使你只是告诉它执行一个静态SQL语句.因此,无论如何,您可能无法通过避免显式准备来保存数据库之旅.
准备好的声明正在被成千上万的人使用,因此经过充分测试(因此可以推断它们是相当安全的).您的自定义解决方案仅供您使用.
您的自定义解决方案不安全的可能性非常高.使用预备陈述.你必须以这种方式维护更少的代码.
准备好的陈述的好处如下:
每个查询只编译一次
mysql将使用更高效的传输格式将数据发送到服务器
但是,准备好的语句只能在每个连接中保留.除非您使用连接池,否则如果您每页只执行一个语句,则没有任何好处.简单的简单查询也不会从更高效的传输格式中受益.
我个人也不会打扰.伪准备语句可能对他们可能提供的安全变量引用有用.