【问题标题】:Do PHP PDO prepared statements need to be escaped?PHP PDO 准备好的语句是否需要转义?
【发布时间】:2019-07-20 22:03:38
【问题描述】:

PDO::Prepare page 上声明,

“通过消除手动引用参数的需要,有助于防止 SQL 注入攻击”

知道了这一点,有没有像 mysql_real_escape_string() 这样的 PHP 函数来处理 PDO 的转义问题?还是 PDO 会为我处理所有逃逸事件?

编辑

我现在意识到我问错了问题。我的问题真的是,“PDO 为我照顾什么?”我现在通过这些答案意识到,它实际上只消除了转义引号的需要。但是我仍然需要对传递给执行函数的值执行任何其他 PHP 清理调用。比如htmlentities()、strip_tags()...等...

【问题讨论】:

  • 世界上没有通用的“消毒”功能。就像现实生活一样:洗手、使用安全套、把钱放在保险箱里都是为了安全。但这并不意味着你的苹果,洗干净,用避孕套包起来,放进安全的箱子里,就被认为是安全的。每个消毒功能都有自己的用途。不要从数据库函数中询问 HTML 安全性。这会很奇怪。
  • @Col。弹片 +1 很好的例子哈哈.....

标签: php pdo


【解决方案1】:

PDO 不会转义变量。变量和 SQL 命令通过 MySQL 连接独立传输。 SQL 标记器(解析器)从不查看值。值只是逐字复制到数据库存储中,而不会造成任何伤害。这就是为什么不需要使用准备好的语句来整理数据的原因。

请注意,这主要是速度优势。使用 mysql_real_escape_string() 你首先在 PHP 中编组你的变量,然后向服务器发送一个低效的 SQL 命令,这不得不再次将实际的 SQL 命令与值隔离开来。这就是为什么人们常说安全优势只是隐含的,而不是使用 PDO 的主要原因。

如果你连接 SQL 命令并且实际上不使用准备好的语句(不好!),那么是的,PDO 仍然有一个转义函数:$pdo->quote($string)

【讨论】:

  • 其实这是不正确的。 pdo 和 adodb 在连接到 mysql 时都使用mysql_real_escape_string()。我看过代码。
  • @Col。弹片 pdo 是用 c++ 编写的,adodb 是用 php 编写的。他们都使用 mysql_real_escape_string() (这是官方 mysql 客户端库的一部分)。您必须在某些时候转义输入,没有其他方法。
  • @The Rook:从svn.php.net/viewvc/php/php-src/trunk/ext/pdo_mysql/… 测量它可能取决于后端驱动程序。新的 mysqlnd 肯定使用真正的准备好的语句,而旧的可能会依赖 PDO_ATTR_EMULATE_PREPARES 和转义/连接。毕竟,如果不可用,这是 PDO 宣传的功能之一。
【解决方案2】:

这里很少有人了解转义是什么以及何时使用它。
转义本身不会使任何数据“安全”。它只是转义分隔符,以区分分隔符和部分数据。 field = 'it's me' 会导致错误,而field = 'it\'s me' 不会。这是逃跑的唯一目的。因此,它仅在您使用引号时才有效。如果你不这样做 - 转义将变得毫无用处。

您是否在占位符中使用引号?不,因此,没有逃避是明智的。

当您绑定变量时,它的工作方式非常不同:它不会将整个查询发送到服务器,而是将您准备好的查询与绑定数据分开发送。所以不能干涉。因此无法进行注射。

【讨论】:

  • 再次感谢@YourCommonSense。 ?
【解决方案3】:

是与否:

  • 您嵌入到语句字符串中的文字需要正常转义。
  • 绑定到准备好的语句的值由库处理。

【讨论】:

  • 所以如果我使用 bindParm 方法,我不需要逃避任何东西来防止注射,对吧?
  • @Patareco 传递给PDOStatement::bindValue()PDOStatement::bindParam() 的值(有一个重要区别!)应该由PDO 正确处理。您不应转义它们,否则它们将转义地存储在数据库中。不过,我不做任何保证; PDO/PHP/MySQL 中可能存在允许注入的错误。您还必须正确处理输出以防止脚本注入。
  • 我的问题只是关于在数据库中插入数据和防止 SQL 注入。你提出了一个我没有考虑过的重要问题。有人可以放一些可能给我带来麻烦的讨厌的 JS,幸运的是 PHP 具有转义 HTML 字符的功能。谢谢你的警告!
【解决方案4】:

如果您准备一个语句并使用bindParambindValue 提供变量,则不需要转义变量。请注意,这些函数假定变量包含一个字符串,因此如果您想使用布尔值或浮点数,请使用第三个参数来绑定值。

【讨论】:

  • 我正在使用准备和执行.....我不使用 bindParam 或 bindValue 函数。
  • @Metropolis:没关系。如果你通过问号?或 :named 参数作为 ->execute() 的参数,它与 bindParam 具有相同的效果。请注意这些应该引用文本列。
【解决方案5】:

您不必担心。 PDO 不要求您在将数据传递到数据库之前对其进行转义。

编辑:为了清楚起见,我的意思是说,只要您将变量传递给您的参数(例如,表单字段的值),您就不必担心它。但是,例如,如果您传递已定义为字符串的变量,那么显然您需要转义该字符串中需要转义的任何内容,以避免破坏语法。但是,这甚至没有多大意义,因为 PDO 的主要优点之一是您将信息从用户传递到数据库而不必自己清理它,而且次数不多(如果有的话?)您将传递您自己定义的字符串。

另外,请确保您仍然为 type 清理数据。例如,如果您期望它是整数,请确保它是一个整数,如果您期望它是,请确保它小于或大于 x,等等。

【讨论】:

  • 好酷....所以所有特殊字符都应该被处理?像 HTML 标签、引号……等等……
  • 假设您将参数绑定到准备好的语句,是的。 (很明显,如果您自己在 PHP 代码中编写文本,例如写入变量,则需要对其进行转义,以免破坏语法。)
  • @Metropolis html 标签与 SQL 完全无关,引号对于绑定无关紧要,因为没有分隔引号 - 所以,没有什么可以逃避的。
  • @Metropolis 转义以防止 SQL 注入与 html 标签等无关。当您将存储的输入输出到网页时,如果它包含您不想解析的 html 等,您仍然需要转义它。
  • @Col。弹片我关于 HTML 的问题被问到,因为我想知道是否需要在我传入的值上使用 htmlentites 来替换语句中的 (?)。
猜你喜欢
  • 2010-11-30
  • 2010-11-05
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 2014-09-03
  • 1970-01-01
相关资源
最近更新 更多