何时应使用预准备语句?总是。100%的时间,使用它。总是;即使您不需要使用它。仍然使用它。

最初我用和做事。然后我学习了SQL注入,所以我正在尝试学习如何使用预准备语句。我了解PDO类的准备和执行函数如何用于防止SQL注入。mysql_connectmysql_query

是否仅当用户输入存储到数据库中时才需要预准备语句?是否仍然可以使用,因为我并没有真正冒着被使用此功能黑客入侵的风险?或者使用预准备语句来执行此操作更安全?我应该对涉及使用MySQL的所有内容使用预准备语句吗?为什么?mysql_num_rows


答案 1

tl/dr

总是。100%的时间,使用它。总是;即使您不需要使用它。仍然使用它。


mysql_*函数已弃用。(注意到大红色方框了吗?)

警告此扩展在 PHP 5.5.0 中被弃用,在 PHP 7.0.0 中被删除。相反,应使用 MySQLiPDO_MySQL 扩展。有关更多信息,另请参阅MySQL:选择API指南和相关常见问题解答。此功能的替代方法包括:

你最好使用PDOMySQLi。使用预准备语句时,这 2 个中的任何一个都足以作为兼容的库。

在没有准备好的陈述/消毒的情况下信任用户输入就像把你的车留在一个糟糕的街区,解锁,钥匙在点火中。你基本上是在说,来吧,拿走我的好东西enter image description here

永远不应该,我的意思是永远不要相信用户输入。除非你想要这个:

SQL Injection

在引用数据并存储数据时,如注释中所述,您永远不能也不应该信任任何与用户相关的输入。除非你 101% 确定用于操作所述数据库/值的数据已硬编码到你的应用中,否则你必须使用预准备语句。

现在来看看为什么应该使用预准备语句。这很简单。防止SQL注入,但以最直接的方式。预准备语句的工作方式很简单,它将查询数据一起发送,但分开(如果这有意义,哈哈) - 我的意思是:

Prepared Statements
Query: SELECT foo FROM bar WHERE foo = ?
Data:  [? = 'a value here']

与它的前身相比,在前身中,您用数据截断了查询,将其作为一个整体发送 - 反过来,这意味着它是作为单个事务执行的 - 导致SQL注入漏洞。

下面是一个伪示例,向您展示预准备语句/绑定的简单性。PHP PDO

$dbh = PDO(....); // dsn in there mmm yeahh
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);

// insert one row
$name = 'one';
$value = 1;
$stmt->execute();

摘自 PHP 手册,用于 PDO 预准备语句


更多阅读


答案 2

TL;DR 如果您的应用接受任何用户输入,则 100% 使用预准备语句


你似乎有一点困惑。首先,请不要使用mysql_*;这些函数已过时,已弃用且不安全。请改用 MySQLiPDO。其次,与预准备语句无关,无论如何都不是PDO功能。在运行查询之前准备语句,而不是在要对行进行计数时在运行查询之后准备语句。mysql_*mysql_num_rows

至于何时准备声明,@Mike'Pomax'Kamermans在评论中钉住了它。如果您曾经使用过用户(甚至是所谓的受信任的用户)曾经接触过的任何数据,或者由任何类型的第三方或第三方应用程序(包括浏览器)生成的数据,请使用预准备语句。只有当100%的数据是硬编码的或完全由代码生成(如简单的计数器变量)时,您才能信任它。

例如,您不能信任:

  • 用户名
  • 密码
  • 电邮地址
  • 用户评论
  • 电话号码
  • 日期
  • 搜索字符串
  • 浏览器客户端字符串
  • 信用卡号码
  • 上载的文件名
  • 以及由用户创建或用户可以操作的任何其他类型的输入。

当然,在将它们放入数据库之前,您应该验证所有这些(例如,检查电子邮件地址是否真的是电子邮件地址)。但即便如此,使用预准备语句也是一种安全的方法。


推荐