准备语句保护您的数据库吗?

时间:2011-08-24 13:09:45

标签: php mysql sql

我知道你们中的一些人可能会关闭这个问题,但我的问题来自你和你的答案。我正在阅读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();

4 个答案:

答案 0 :(得分:12)

两者。准备好的语句将保护您免受SQL注入的侵害,当且仅当您以正确的方式使用它们时。如果您仍在为表/列名称插入变量,那么只使用'使用'预处理语句将无济于事。

$stmt = "SELECT * FROM $table WHERE $column = ?"; //not good...

答案 1 :(得分:11)

准备好的陈述没有。只要所有不受信任的数据都通过参数传递而不是插入到语句中,绑定参数就会保护语句(而不是整个数据库)。当人们使用预准备语句时,他们几乎总是使用绑定参数,因此这两个名称经常混为一谈。

  1. 准备声明
  2. 使用变量作为附加参数运行语句
  3. mysql_real_escape_string几乎总能完成这项工作,但由于它为流程添加了额外的步骤,因此更容易出现人为错误。

    1. 转义每个变量
    2. 将变量连接到SQL语句
    3. 运行声明

答案 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)您不要忘记转义所有输入