单独使用准备好的语句进行占位符绑定是不是过大?
Posted
技术标签:
【中文标题】单独使用准备好的语句进行占位符绑定是不是过大?【英文标题】:Is It Overkill To Use Prepared Statements for Placeholder Binding Alone?单独使用准备好的语句进行占位符绑定是否过大? 【发布时间】:2011-06-02 23:44:29 【问题描述】:知道很多人使用准备好的语句,仅用于占位符绑定。也就是说,他们不打算多次发布具有不同值的相同语句。他们只是觉得以这种方式使用 PS 更安全。
我对 mysql 的 PS 的理解,是 SQL 是作为单次传输发送的,然后是一个或多个传输来发送值。因此,使用 PS 进行单个查询的效率低于使用普通查询,后者在单个传输中完成。
PS 提供的安全优势是否会比效率损失更重要?我不这么认为,因为我认为在将值添加到 SQL 之前正确转义值并不难。
你有什么想法?
【问题讨论】:
这就是为什么存储过程要好得多。这只是一个调用,因为 sproc 已经存在于数据库中 - 所以你不需要准备它。 sprocs 也有参数,所以你不能注入(请不要引用 WTF 动态 sql 示例)加上你只需要给你的应用程序用户 EXECUTE 权限,没有选择、插入、删除、删除、截断、显示等 - 你认为有多安全它得到了?? 【参考方案1】:准备好的语句被编译并存储在 DBMS 上。这些语句可以被缓存和重用。
想象一下多次点击同一页面的好处。
此外,某些数据库引擎(例如 Oracle)可能会施加硬语句限制并相信我(我从经验中知道),您不会想用尽这一点。
【讨论】:
+1:对所有事情都使用准备好的语句。罕见的例外是脚本仅作为数据迁移的一部分执行一次。 为后续查询缓存查询是我迄今为止看到的唯一令人信服的论点。 准备好的语句模板缓存多长时间?【参考方案2】:Do the security benefits PS offer out weigh the loss in efficiency?
我认为是的,他们可能会这样做。但是,即使使用准备好的语句确实非常低效,收集一些数据表明这种低效率对您的操作造成了某种明显的障碍,难道不是谨慎的做法吗?如果它的效率较低但您的 Web 服务器仍然可以很好地处理它,这是否太重要了?您必须先量化差异是什么,然后才能说出它的重要性。
事实上,您是在权衡安全性与对什么可能是有效的相当模糊的想法。这可能是错误的方式。
编辑:回应第一条评论:
当然,这个论点可以反过来说,你可以争辩说,如果有的话,应该对准备好的语句比查询构建更安全多少进行某种评估。但这比您对脚本效率的担忧更不适合量化。
我建议每个人的目标是达成一个解决方案,让他们有足够的信心保护他们免受攻击;当然,如果您虔诚地使用准备好的语句,或者您在需要时认真地转义查询变量,那么您已经做到了。 IMO,您真正应该考虑的是:我的方法如何系统避免 SQL 漏洞利用?它为错误的发生提供了多大的范围,当您在创建会出现问题的代码时未能发现?
如果每次执行数据库查询时,您都必须认真记住遍历每个将要使用的变量并为此目的对其进行转义,这会导致代码冗长,并且您很可能会忽略某些变量。切割和粘合琴弦在本质上也有些不整洁。如果您有一定程度的抽象要求您识别每个查询变量及其类型,并且如果您不这样做会导致查询失败,那么无论是否使用预准备语句提示,您都是已经以更系统的方式做事,这可以帮助您避免疏忽,从而绕过您在其他任何地方的谨慎保护。
【讨论】:
我可以支持你的论点,但你必须说服我准备好声明而不是正确转义值的安全性。如果转义值可以/与 PS 一样安全,那么两者会相互抵消,而您只剩下 PS 对数据库服务器进行更多访问。 @mellowsoon 假设每个查询都正确地转义了每个值,并且转义 (mysql_escape_string
-- doh!) 在所有情况下都可以正常工作 -- 还要考虑到即使 mysql_real_escape_string
@987654321 @ ("...旨在防止 SQL 注入的函数用于实际触发它。")。是的……不。使用占位符也只是更整洁。
关于 mysql_real_escape_string 的文章非常有趣,我很高兴我读到了它,但多年来我看到了类似的错误,这些错误使准备好的语句也容易受到攻击。就更整洁而言,我仍然使用没有准备好的语句的占位符。我的数据库抽象引用了这些值,而不是单独发送它们。
我没有发表该评论。但作为补充说明,没有任何理由在 php 中使用 mysql
接口。它已经过时了。您应该使用 mysqli
扩展来代替它(无论您是否打算使用准备好的语句),或者使用 PDO。
有关不小心使用 mysql_real_escape_string()
的示例,请参阅此答案:***.com/questions/4795899/… 并阅读 cmets(问题在评论中,而不是答案本身)。使用准备好的语句可以避免这种情况。如果没有准备好的语句也可以避免这种情况,但您可能会错过。【参考方案3】:
我认为这不应该是效率问题。我怀疑您是否会测量出有意义的差异,尤其是与数据库调用的网络延迟和其余代码引入的低效率相比时。
单独防范 SQL 注入的好处是值得自己付出代价的。
我认为这是 Donald Knuth 警告过的一个微优化示例。
但不要推测或依赖你在这里得到的意见。成为一名科学家并获取一些数据。如果数据支持你的情况,那就去吧。
【讨论】:
当你每秒处理 5k 个连接时,你还认为它是微优化吗?以上是关于单独使用准备好的语句进行占位符绑定是不是过大?的主要内容,如果未能解决你的问题,请参考以下文章