【问题标题】:Dynamic arguments in prepared statements准备好的语句中的动态参数
【发布时间】:2013-02-11 15:02:36
【问题描述】:

人!

我有这个查询,它从$_POST 获取它的WHERE 参数。问题是我想动态获取两个比较值,而不为每个值创建查询。我现在拥有的是:

$what = $mysqli->real_escape_string($_POST['what']);
........
$query = "SELECT * FROM list WHERE ";
$query .= $what . " = ? LIMIT 0,10";
........
$stmt->bind_param('s', $what);

我的第一个问题:这在实践中有多安全?由于我无法同时绑定两个参数,是否还有其他更好的方法可以管理同一件事?

我遇到的第二个问题是:我想将= ? 更改为LIKE %?%,但无法正常工作。我尝试使用 CONCAT('%', ?, '%') (不好,我知道) ,但它仍然无法正常工作。 基本上我最终想要实现的是:WHERE ? LIKE %?%。可能吗?你能帮我解决这个问题吗?

干杯,亚历克斯

【问题讨论】:

  • 这不安全,请使用白名单。
  • 即使您可以避免 SQL 注入,如果不经常检查您的表中的存在的列 - 绝对按照建议使用白名单。
  • 用like try: WHERE .. LIKE ? 然后bind_param('s', '%test%')
  • 我得到了 LIKE 来配合 Mogria 的建议:$where = '%' . $_POST['where'] . '%';
  • @vulkoingim 问题是用户也可以输入 % 符号。如果您不想要这个,请参阅我的答案中的链接,也可以正确地逃避它。 PDO 不会那样做。

标签: php mysql mysqli prepared-statement


【解决方案1】:

mysql_real_escape_string 或类似函数不会转义反引号 (`),因此您的应用程序容易受到 SQL 注入攻击。

只需为所有列定义一个白名单并检查该列是否在数组中。

要在LIKE %?% 之后搜索,只需在搜索词的前面和后面附加一个%。要正确逃避这件事,请参阅:Escaping MySQL wild cards

【讨论】:

    【解决方案2】:

    只需检查$where 的严格参数集即可:

    if (!in_array($where, array("table1", "table2"))) {
       //do smth with wrong parameter
    }
    

    请注意,in_arrayO(N) 的复杂性运行,因此如果您的参数集很大,最好使用带有表名的关联数组作为键。

    【讨论】:

      【解决方案3】:

      您可以进行这样的动态查询,但您的网站将容易受到 SQL 注入的攻击。

      【讨论】:

        【解决方案4】:

        mysql_real_escape_string 转义反引号,但您可以手动转义它们。
        将所有转义的东西移到某种帮助库中也是个好主意。因此,您将在 2 行中获取数据:

        $sql  = "SELECT * FROM list WHERE ?n = ?s LIMIT 0,10";
        $data = $db->getAll($sql, $_POST['what'], $_POST['where']);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-11
          • 2014-03-20
          • 2018-12-03
          相关资源
          最近更新 更多