【问题标题】:Should I use prepared statements if I am working with already saved data如果我正在处理已经保存的数据,我应该使用准备好的语句吗
【发布时间】:2014-01-10 13:13:23
【问题描述】:

从客户端接收到的数据正在使用准备好的语句(查询)进行保存。例如:

 if ($stmt = $mysqli->prepare("INSERT INTO table_1 VALUES (?, ?, ?);"))
 {
     $stmt->bind_param(/* data */);
     $stmt->execute();
     // ...
 }

如果稍后我想要处理客户的数据,我是否必须再次使用准备好的语句?仅使用经典查询是否有风险?例如:

if ($stmt = $mysqli->prepare("SELECT * FROM table_2 WHERE something = ?;")
{
    $stmt->bind_param("s", /* Selected value from the `table_1` */ );
    $stmt->execute();
    // ...
}

【问题讨论】:

  • 如果没有用户交互,则不必使用prepare语句。
  • 在第一个示例中是用户交互,但在第二个示例中,我只是在处理来自客户端的已保存数据......所以保存的数据是否足够安全?而且我不必使用准备好的语句/清理数据?我理解对了吗?
  • 您旁边的其他人是否可以访问数据?如果是,则应使用 prepare 语句,否则不必。
  • 如果用户输入构成查询的一部分,您应该使用准备好的语句。除非您正确清理用户输入,否则可以制作恶意 SELECT 查询来执行删除表等额外操作。准备好的语句是最安全的方法。
  • @Anam,您的建议确实不够。 SQL 注入利用我们在后续查询中重用存储在数据库中的数据这一事实并不少见——这是一种间接攻击。只需使用参数!没有充分的理由不这样做。

标签: php mysql pdo mysqli prepared-statement


【解决方案1】:

您应该始终使用参数化查询,因为它们可确保数据在数据库级别正确转义。这是您可以自己处理的事情,但这样做很容易出错。

请注意,查询必须正确参数化。仅仅使用prepare 是不够的。

考虑一下您在存储到另一个表的列中有一个撇号。如果没有正确转义,你会得到一个错误。

【讨论】:

  • 我同意。使用参数化查询绝对不会丢失任何东西,因此请始终使用它们,即使您提供了值。每个参数最多需要多行代码。
  • @Mike,如果你使用 PDO 会更容易;无需绑定,只需将数组传递给 execute()。
【解决方案2】:

是的,如果您的查询可以包含任何用户输入(例如从用户搜索词中形成一个指定的 WHERE 子句),您应该使用准备好的语句/参数化查询。

允许用户在查询中输入的最大危险不是持久化恶意数据,而是SQL injection。这可以在任何类型的查询上完成,因此,在您运行包括用户输入在内的查询时,您应该始终使用参数化的准备好的语句(或根据您的 RDBMS 规则手动转义所有用户输入)。

【讨论】:

  • 如果您使用 PDO,即使对于不支持它们的 RDBMS,您也可以使用准备好的语句(客户端)。
猜你喜欢
  • 2014-05-09
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
  • 2011-11-28
  • 1970-01-01
相关资源
最近更新 更多