我应该何时使用准备好的陈述?

G.S*_*NGH 11 php security sql-injection prepared-statement

最初我使用mysql_connect和mysql_query来做事.然后我学习了SQL注入,所以我试图学习如何使用预处理语句.我理解PDO类的准备和执行函数如何有助于防止SQL注入.

但是,只有在用户输入存储到数据库中时才需要准备语句.还是可以继续使用mysql_num_rows,因为我真的没有冒这个功能被黑客入侵的风险吗?或者使用预准备语句来执行此操作更安全吗?我是否应该为涉及使用mysql的所有内容使用预准备语句?为什么?

我真的很感激任何答案和反馈.谢谢.

Dar*_*ren 33

TL/DR

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


mysql_*函数已弃用.(注意大红色的盒子?)

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

你最好还是使用PDO或者MySQLi.2在使用预准备语句时,其中任何一个都可以作为兼容库.

信任用户输入而没有预先准备好的声明/消毒它就像把车停在一个不好的社区,解锁并点着钥匙.你基本上是在说,只是来吧,拿走我的好东西在此输入图像描述

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

SQL注入

参考数据并存储它,如评论中所述,您永远也不应该信任任何与用户相关的输入.除非您有101%确定用于操作所述数据库/值的数据是硬编码到您的应用程序中,否则您必须使用预准备语句.

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

Prepared Statements
Query: SELECT foo FROM bar WHERE foo = ?
Data:  [? = 'a value here']
Run Code Online (Sandbox Code Playgroud)

与其前身相比,您使用数据截断查询,将其作为整体发送 - 反过来,这意味着它作为单个事务执行 - 导致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();
Run Code Online (Sandbox Code Playgroud)

摘自PHP手册中的PDO准备语句


更多阅读


eli*_*ide 5

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


你似乎有点困惑。首先,请不要使用mysql_*; 该mysql_*功能是过时的,过时和缺乏安全感。使用MySQLiPDO代替。其次,mysql_num_rows与准备好的语句无关,无论如何都不是 PDO 功能。在运行查询之前准备语句,而不是在要计算行数时准备语句。

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

例如,您不能信任:

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

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