今天得知php中使用pdo的时候,并不一定能避免sql注入的问题,PDO::ATTR_EMULATE_PREPARES,默认是true,通过查资料我得知如果这里是true,则启动模拟预编译,false则使用本地预处理语句,网上其他资料告知:如果是模拟预编译的话,则还是可能导致sql注入,请大神赐教这两种编译的区别,还有如果还是可能导致sql注入的话,为什么其他资料上从为提及过这个问题?是否开发的时候时候pdo也需要加上这句
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false)才能达到真正意义上的防sql注入?
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
开发的时候最好是加上这句
$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服务器)。总之,为了安全,那一点性能损耗算得了什么,如果没有什么理由不加,那还是加上吧。
为什么PDO默认要模拟预处理,就是因为有些数据库如SQLite不支持预处理.
模拟预处理也是能防止SQL注入的,如果不能,请举例.
像
medoo.php这个基于PDO的查询构造器(Query Builder)封装,medoo连PDO预处理参数化查询都没有使用,
直接就是
PDO::quote转义用户输入后,用query/exec执行查询.我理解的模拟预处理本质就是
PDO::quote.MySQLi中类似
PDO::quote的东西叫做mysqli_real_escape_string.