我知道你们中的一些人可能会关闭这个问题,但我的问题来自你和你的答案。我正在阅读SQL注入的过去两小时的问题和答案以及如何保护您的数据库。我看到的大量网页和教程也是如此。
我发现有一半的人声称准备语句可以保护你的数据库,另外50人声称它不是。
另一方面,我读到mysql_real_escape_string完成了这项工作,其他人则认为不是。
我的问题是谁相信?
另外,这是一个适当的准备声明吗?
$stmt = $dbh->prepare("SELECT phpro_user_id, phpro_username, phpro_password FROM phpro_users
WHERE phpro_username = :phpro_username AND phpro_password = :phpro_password");
/*** bind the parameters ***/
$stmt->bindParam(':phpro_username', $phpro_username, PDO::PARAM_STR);
$stmt->bindParam(':phpro_password', $phpro_password, PDO::PARAM_STR, 40);
/*** execute the prepared statement ***/
$stmt->execute();
答案 0 :(得分:12)
两者。准备好的语句将保护您免受SQL注入的侵害,当且仅当您以正确的方式使用它们时。如果您仍在为表/列名称插入变量,那么只使用'使用'预处理语句将无济于事。
$stmt = "SELECT * FROM $table WHERE $column = ?"; //not good...
答案 1 :(得分:11)
准备好的陈述没有。只要所有不受信任的数据都通过参数传递而不是插入到语句中,绑定参数就会保护语句(而不是整个数据库)。当人们使用预准备语句时,他们几乎总是使用绑定参数,因此这两个名称经常混为一谈。
mysql_real_escape_string
几乎总能完成这项工作,但由于它为流程添加了额外的步骤,因此更容易出现人为错误。
答案 2 :(得分:2)
这是一个很好的讨论。您的问题假设有一种技术可以“保护您的数据库”。事实上,没有一种技术最适合所有情况。因此,您需要学习在不同情况下使用多种解决方案。
请参阅我的演示文稿SQL Injection Myths and Fallacies,其中详细介绍了防御SQL注入时需要了解的所有内容。
我还在我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming中介绍了SQL注入。
答案 3 :(得分:0)
在某些情况下,无法使用预先准备好的陈述。例如,当您必须动态生成IN()
子句的内容时,如果您已动态选择以逗号分隔的值进入WHERE col IN (?)
,则无法执行IN()
。此外,如果需要在SELECT
子句中动态生成列列表,则必须通过构建SQL字符串来实现。
底线是,两者都有自己的位置。准备好的语句非常适用于预定查询或必须多次执行的查询。转义动态SQL非常出色1)您必须具有最大的灵活性,2)您不要忘记转义所有输入。