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

时间:2014-07-28 05:25:23

标签: php prepared-statement

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

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

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

4 个答案:

答案 0 :(得分:34)

<强> TL / DR

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


不推荐使用

mysql_*个函数。 (Notice the big red box?

  

警告此扩展程序在PHP 5.5.0中已弃用,已被删除   在PHP 7.0.0中。相反,MySQLiPDO_MySQL扩展应为   用过的。另请参阅MySQL: choosing an API指南和related FAQ了解更多信息   信息。该功能的替代方案包括:

     

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

信任用户输入而没有准备好的陈述/消毒它就像把车停在一个不好的街区,解锁并点着钥匙。你基本上是在说,只是来看看我的好东西enter image description here

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

SQL Injection

在参考数据并存储它时,如评论中所述,您可以从不,并且绝不应信任任何与用户相关的输入。除非您确信用于操作所述数据库/值的数据是硬编码到您的应用程序中,否则您必须使用预准备语句。

现在说明为什么要使用预准备语句。这很简单。要防止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();

Taken from PHP Manual for PDO Prepared Statements


更多阅读

答案 1 :(得分:3)

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


你似乎有点混乱。首先,请don't use mysql_*; mysql_*函数已过时,deprecated且不安全。请改用MySQLiPDO。其次,mysql_num_rows与预准备语句无关,而且无论如何都不是PDO功能。您在运行查询之前准备语句,而不是在您想要计算行数时之后准备语句。

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

例如,你不能相信:

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

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

答案 2 :(得分:0)

Mysql_*已被弃用,以便更好地切换mysqli_*PDO

用于防止sql注入(mysql): - How can I prevent SQL injection in PHP?

准备好的语句(这些是由数据库服务器与任何参数分开发送和解析的SQL语句。)用于每个用户生成的查询数据。

就像发布您使用查询匹配/获取记录到db的数据一样。这意味着当您使用表单数据触发查询时。

答案 3 :(得分:0)

这有两个解决方案 -

01-使用准备好的陈述

为了防止SQL注入,我们必须使用一些名为prepare语句的东西,它使用绑定参数。准备语句不会将变量与SQL字符串组合在一起,因此攻击者无法修改SQL语句。 Prepared Statements将变量与已编译的SQL语句组合在一起,这意味着SQL和变量是分开发送的,变量只是被解释为字符串,而不是SQL语句的一部分。

02-使用mySQLi准备好的语句。

使用以下步骤中的方法,您不需要使用任何其他SQL注入过滤技术,例如mysql_real_escape_string()。这是因为使用预准备语句不可能进行传统的SQL注入。

例如 -

$name = $_GET['username'];

if ($stmt = $mysqli->prepare("SELECT password FROM tbl_users WHERE name=?")) {

    // Bind a variable to the parameter as a string. 
    $stmt->bind_param("s", $name);

    // Execute the statement.
    $stmt->execute();

    // Get the variables from the query.
    $stmt->bind_result($pass);

    // Fetch the data.
    $stmt->fetch();

    // Display the data.
    printf("Password for user %s is %s\n", $name, $pass);

    // Close the prepared statement.
    $stmt->close();

}

您可以找到有关此表单的更多信息 - http://www.wikihow.com/Prevent-SQL-Injection-in-PHP