【问题标题】:Should I bind internal values when preparing queries in PDO?在 PDO 中准备查询时是否应该绑定内部值?
【发布时间】:2016-06-17 02:35:22
【问题描述】:

有以下代码

<?php
$age = get_age(); // a generated or random unsigned integer
$db->prepare("SELECT * FROM Customers WHERE name = :name AND age = :age");
$db->bindValue('name', $_POST['name']);
$db->bindValue('age',  $age, PDO::PARAM_INT);
$db->execute();

我是否应该绑定“年龄”,即使它不是来自用户(即外部)?

如果我有一个固定的年龄,或者它是我以某种方式生成的,我应该这样做吗?

<?php
$age = get_age(); // <- Of course I made sure this is an unsigned integer
$db->prepare("SELECT * FROM Customers WHERE name = :name AND age = $age");
$db->bindValue('name', $_POST['name']);
$db->execute();

各有优缺点还是只是个人喜好?

【问题讨论】:

  • 如果它是内部的,它可能是从其他一些攻击媒介从外部到达那里的。这就是 2 级 sql 注入的定时炸弹如何随着繁荣而变成 1 级。只是说。
  • 从 PHP 中绑定任何值是一个很好的做法,并且尽可能不要将变量数据直接插入 SQL。这可以防止以后的代码更改发生意外。此外,在准备语句时,它已准备好进行多次快速执行,而无需每次执行开销。
  • @Drew 好的,但我只是直接输入年龄,我的意思是AND age = 17。我应该这样做还是更好AND age = :age然后bindValue('age', 17, PDO::PARAM_INT)
  • 我个人不会绑定,但我有兴趣了解@Drew 所说的“其他攻击向量”
  • 就我个人而言,我总是绑定所有内容,然后我什至不必考虑 SQL 注入。任何时候您不绑定时,您都必须知道确切地该变量是如何到达那里的,除了在查询之前对脚本中的值进行硬编码之外,您可能必须遵循心理纸迹,以确保用户永远不会直接或间接地触摸它。另外值得一提的是,准备好的语句使您的查询可重用,因此如果您想将其从 17 更改为 56,您不必再次重新发送整个查询,只需重新发送值即可。

标签: php mysql pdo prepared-statement


【解决方案1】:

在 PDO 中准备查询时是否应该绑定“内部”值?

是的。

您应该了解愚蠢的人工示例和成熟的现实生活代码在其生命周期内的区别。

如果您想学习如何编写成熟的代码,请考虑以下几点:

  • 有一种东西叫做一致性。你的第一个例子看起来是一致的,而第二个不是。毕竟,这只是一个简单的规则——每个变量都应该通过占位符进入查询。为什么要阻碍你的发展,让自己困惑于思考例外情况?
  • 每个应用程序都会发展和演变。 $age 的来源将来可能会改变。
  • 并非每个代码都只是一个意大利面条碗,SQL 查询在现场运行。 一些程序员能够掌握关注点分离 的概念,从而使他们的应用程序模块化且灵活。在这样的应用程序中,在执行查询时,数据库层完全不知道数据来自哪里,它是否“安全”,也不知道“安全”是什么意思。
  • 所有这些绑定麻烦都与“外部”变量无关。但只是为了查询的完整性。无论什么“内部”值都可能具有不正确的格式,直接放入查询中。想象一下您的函数失败并返回一个空字符串。在第二种情况下会导致 SQL 错误。 您必须了解您正在绑定您的价值观not for Bobby Tables but for Sarah O'Hara

【讨论】:

    【解决方案2】:

    是的,由于 sql 语句中的使用参数,您需要在上下文中进行绑定(请参阅:http://php.net/manual/fr/pdostatement.bindvalue.php)。

    或者,您可以这样做:

    <?php
    $age = get_age(); // <- Of course I made sure this is an unsigned integer
    $sth= $db->prepare("SELECT * FROM Customers WHERE name = ? AND age = ?");
    $values = array("john", $age);
    $sth->execute($values);
    

    【讨论】:

      【解决方案3】:

      在这种情况下,这只是个人喜好。我认为当这是一个大查询时,这更有助于理解查询。但是,如果有一天有人更改函数 get_age() 以按用户检索数据,这可能是危险的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-02
        • 1970-01-01
        • 1970-01-01
        • 2015-12-08
        • 2015-07-13
        • 1970-01-01
        相关资源
        最近更新 更多