【发布时间】:2018-12-03 13:44:37
【问题描述】:
我读了很多文章,说使用准备好的语句非常安全,并且可以很好地防止 SQL 注入。我在没有使用准备好的语句的情况下建立了一些网站。但是在阅读了所有这些文章之后,我正在考虑使用准备好的语句来更改整个代码。
我的问题
是否有必要总是使用准备好的语句?或者是否有任何情况下正常的语句足以胜过准备好的语句?
【问题讨论】:
标签: php mysqli sql-injection
我读了很多文章,说使用准备好的语句非常安全,并且可以很好地防止 SQL 注入。我在没有使用准备好的语句的情况下建立了一些网站。但是在阅读了所有这些文章之后,我正在考虑使用准备好的语句来更改整个代码。
我的问题
是否有必要总是使用准备好的语句?或者是否有任何情况下正常的语句足以胜过准备好的语句?
【问题讨论】:
标签: php mysqli sql-injection
刚发现你的问题,我想起了我过去的美好时光。我也发现很难实现准备好的语句,因为乍一看,没有它感觉很容易编码。然后在另一次,我使用 PHP 制作了一个让我感到自豪的登录系统。虽然完全从头开始制作,但感觉很棒。但是,我犯了一个错误,没有使用它们,然后我检查了谷歌如何绕过登录系统。第一个技巧让我头疼,因为我现在可以在不知道用户名或密码的情况下登录我的网页,只需使用一些字符,如'-',然后我就进入了我的网页。所以我一路返回并使用参数化查询来保护它,现在它是安全的。既然你我都是初学者,这些东西肯定会让我们头疼。此外,仅当您从用户输入中接受某些内容时,您才需要使用它们。否则你很高兴。只需四处寻找其他漏洞,例如 XSS 等。这些也很危险。祝你好运
【讨论】:
如果您有一个完全硬编码的 SQL 查询,并且在 SQL 中不需要 PHP 变量,那么非准备语句就足够了。
这是一个例子:
$result = $mysqli->query("SELECT * FROM mytable WHERE updated_at > NOW() - INTERVAL 7 DAY");
查询是独立的。它只是一个固定的字符串,完全由您的应用程序控制。任何不受信任的内容都不会影响查询。
如果您的查询需要一些可变部分,则使用查询参数,如下所示:
$stmt = $mysqli->prepare("SELECT * FROM mytable WHERE updated_at > NOW() - INTERVAL ? DAY");
$stmt->bind_param("i", $number_of_days);
$stmt->execute();
查询参数的重点是将可能不受信任的内容与 SQL 解析步骤分开。通过使用参数,绑定变量的值直到 SQL 被解析后才与查询结合。因此,绑定参数无法影响查询的逻辑——该参数将被限制为在查询中充当单个标量值。
【讨论】:
mysqli_real_escape_string)而不是预先准备好的语句,但是它可能会让你一头雾水,然后你就有麻烦了;此外,转义的实现可能很糟糕(这就是为什么首先有一个名为mysqli_real_escape_string 的函数的原因)。正如上面 Bill 所示,养成始终使用参数化语句的习惯是一个非常好的习惯。
mysql_ 函数已经死了,当你修复旧代码时,真的修复它!