php PDO的模拟预编译语句和本地预处理语句区别

今天得知php中使用pdo的时候,并不一定能避免sql注入的问题,PDO::ATTR_EMULATE_PREPARES,默认是true,通过查资料我得知如果这里是true,则启动模拟预编译,false则使用本地预处理语句,网上其他资料告知:如果是模拟预编译的话,则还是可能导致sql注入,请大神赐教这两种编译的区别,还有如果还是可能导致sql注入的话,为什么其他资料上从为提及过这个问题?是否开发的时候时候pdo也需要加上这句$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false)才能达到真正意义上的防sql注入?

提问者女神的闺蜜爱上我提问时间:2017-03-16 11:22我来回答
1回答
巴扎黑
回复巴扎黑赞同0已被提问者采纳7个月前

开发的时候最好是加上这句$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false),这样如果支持本地预处理则会使用本地预处理,在不支持的情况下会自动使用模拟预处理方式。

使用模拟预处理的方式是在客户端本地执行预处理的模拟,最终将拼好的sql语句发送到mysql服务器进行执行(实际上就是完成了字符串拼接,据说对表名使用占位符会出现sql注入,我没有验证过),mysql会对sql进行parsing->resolution->optimization->execution。使用本地预处理方式则是分两步:第一步是prepare阶段,发送带有占位符的sql语句到mysql服务器(parsing->resolution),然后就可以多次发送占位符参数给mysql服务器进行执行(多次执行optimization->execution)。

使用模拟预处理方式实际上就是一次发送完整的sql给mysql执行,不需要mysql做额外处理(如保存会话状态等),因此性能比较好一些,而使用本地预处理则需要多次发送,mysql服务器需要保存会话状态,性能上会有一些损耗。

另外,使用本地预处理的一个好处是在prepare阶段就能检测出sql语句的错误,而使用模拟的预处理方式制定在exec阶段才能发现(因为模拟方式拼接好sql在exec阶段才会发送到mysql服务器)。

总之,为了安全,那一点性能损耗算得了什么,如果没有什么理由不加,那还是加上吧。