如何在PHP中阻止SQL注入?

如果插入用户输入而不修改SQL查询,则应用程序容易受到SQL注入的攻击,如下例所示:

$unsafe_variable = $_POST['user_input']; mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

这是因为用户可以输入类似的内容value'); DROP TABLE table;--,查询变为:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

可以采取哪些措施来防止这种情况发生?


暮色呼如
浏览 617回答 7
7回答

慕桂英3389331

如果您使用的是最新版本的PHP,则mysql_real_escape_string下面列出的选项将不再可用(尽管mysqli::escape_string它是现代版本)。这些天,该mysql_real_escape_string选项只适用于旧版PHP上的遗留代码。您有两个选项 - 转义您的特殊字符unsafe_variable,或使用参数化查询。两者都可以保护您免受SQL注入。参数化查询被认为是更好的做法,但在使用它之前需要在PHP中更改为更新的MySQL扩展。我们将首先覆盖较低影响的字符串。//Connect$unsafe_variable&nbsp;=&nbsp;$_POST["user-input"];$safe_variable&nbsp;=&nbsp;mysql_real_escape_string($unsafe_variable);mysql_query("INSERT&nbsp;INTO&nbsp;table &nbsp;(column)&nbsp;VALUES&nbsp;('"&nbsp;.&nbsp;$safe_variable&nbsp;.&nbsp;"')");//Disconnect另请参见mysql_real_escape_string功能的详细信息。要使用参数化查询,您需要使用MySQLi而不是MySQL函数。要重写您的示例,我们需要类似以下内容。<?php &nbsp;&nbsp;&nbsp;&nbsp;$mysqli&nbsp;=&nbsp;new&nbsp;mysqli("server",&nbsp;"username",&nbsp;"password",&nbsp;"database_name"); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TODO&nbsp;-&nbsp;Check&nbsp;that&nbsp;connection&nbsp;was&nbsp;successful. &nbsp;&nbsp;&nbsp;&nbsp;$unsafe_variable&nbsp;=&nbsp;$_POST["user-input"]; &nbsp;&nbsp;&nbsp;&nbsp;$stmt&nbsp;=&nbsp;$mysqli->prepare("INSERT&nbsp;INTO&nbsp;table&nbsp;(column)&nbsp;VALUES&nbsp;(?)"); &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;TODO&nbsp;check&nbsp;that&nbsp;$stmt&nbsp;creation&nbsp;succeeded &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;"s"&nbsp;means&nbsp;the&nbsp;database&nbsp;expects&nbsp;a&nbsp;string &nbsp;&nbsp;&nbsp;&nbsp;$stmt->bind_param("s",&nbsp;$unsafe_variable); &nbsp;&nbsp;&nbsp;&nbsp;$stmt->execute(); &nbsp;&nbsp;&nbsp;&nbsp;$stmt->close(); &nbsp;&nbsp;&nbsp;&nbsp;$mysqli->close();?>你想要阅读的关键功能就是mysqli::prepare。此外,正如其他人所建议的那样,您可能会发现使用PDO之类的步骤来增加抽象层是有用的/更容易的。请注意,您询问的案例非常简单,更复杂的案例可能需要更复杂的方法。特别是:如果要根据用户输入更改SQL的结构,参数化查询将无济于事,并且不需要转义所需的转义mysql_real_escape_string。在这种情况下,您最好通过白名单传递用户的输入,以确保只允许“安全”值。如果您在条件中使用来自用户输入的整数并采用该mysql_real_escape_string方法,您将在下面的注释中遇到Polynomial描述的问题。这种情况比较棘手,因为整数不会被引号括起来,所以你可以通过验证用户输入只包含数字来处理。可能还有其他我不知道的情况。您可能会发现这是一个有用的资源,可以解决您可能遇到的一些更微妙的问题。

尚方宝剑之说

我建议使用PDO(PHP数据对象)来运行参数化SQL查询。这不仅可以防止SQL注入,还可以加快查询速度。通过使用PDO,而不是mysql_,mysqli_和pgsql_功能,你让你的应用程序从数据库中多了几分抽象的,因为你必须选择数据库提供者很少发生。

临摹微笑

使用PDO和准备的查询。($conn是一个PDO对象)$stmt = $conn->prepare("INSERT INTO tbl VALUES(:id, :name)");$stmt->bindValue(':id', $id);$stmt->bindValue(':name', $name);$stmt->execute();
打开App,查看更多内容
随时随地看视频慕课网APP