带有几个可选搜索词的参数化查询

Posted

技术标签:

【中文标题】带有几个可选搜索词的参数化查询【英文标题】:Parameterized query with several optional search terms 【发布时间】:2011-05-25 18:15:16 【问题描述】:

我有一个包含大量数据的 Web 应用程序,以及一个包含多个字段(例如名称、状态、日期等)的搜索/过滤功能。我一直在对常规(非搜索)查询使用这样的参数化查询:

$id = $_POST['itemID'];
$db = mysqli_connect($host, $username, $password, $database);
$sql_query = "SELECT * FROM tbl_data WHERE ID = ?";
$stmt_query = mysqli_prepare($db, $sql_query);
mysqli_stmt_bind_params($stmt_query, "i", $id);
mysqli_stmt_execute($stmt_query);

//and so on..

如何使用多个可选参数防止 SQL 注入?最多可以设置 10 个单独的参数,可以设置也可以不设置。

在问题似乎不清楚时进行编辑

我的示例是一个参数,它不是可选的。我知道这可以防止 sql 注入。我将如何使用 10 个参数来执行此操作,其中一个或多个可以同时设置?例如。像这样的查询:

SELECT * FROM tbl_data 
WHERE NAME = ? 
AND STATUS = ? 
AND DATE = ? 
AND PARAM4 = ? 
AND PARAM5 = ?

用户只想搜索姓名和日期。我将如何进行绑定?检查 100 种可能的搜索词组合中的每一种并不是一个好主意。

【问题讨论】:

您在准备好的语句上使用绑定参数,因此您会自动受到 sql 注入保护。 SQL 注入仅在您使用源自用户提交的未检查(非转义)内容将查询构建为字符串时才会出现。绑定的参数会被数据库驱动自动转义,所以你不用担心。 @Lee,不,他不是。在这种特殊情况下,不必担心。 【参考方案1】:

您已经受到 sql 注入的保护,因为您正在使用 mysqli_stmt_bind_params,它会为您正确转义。

编辑。 你可以切换到一些数据库框架来获得干净漂亮的代码。

否则...这是非常古老的意大利面条风格...但我喜欢它:D

扩展代码以使用未知数量的参数非常容易。您应该只循环您的参数,同时 1. 使用问号符号构建您的查询字符串,并将您的参数添加到一个数组中,您将传递给 maxdb_stmt_bind_param (资源 $stmt ,字符串 $types ,数组 & $var)。

所以它看起来像这样。它假设至少有一个参数(但避免这种情况很简单)。

$sql = "SELECT * FROM tbl_data WHERE ";
$and = '';
$types = '';
$parameters = array();
foreach($_POST as $k => $v) 
  // check that $k is on your whitelist, if not, skip to the next item
  $sql .= "$and $k = ?";
  $and = " AND ";
  $parameters[] = $v;
  $types .= 's';

$stmt_query = mysqli_prepare($db, $sql);
mysqli_stmt_bind_params($stmt_query, $types, $parameters);

【讨论】:

@Palantir 谢谢,我知道这行得通,但我正在寻找一种将它与 10 个不同参数一起使用的方法,这些参数可能会或可能不会被设置。有关详细信息,请参阅编辑后的问题。 谢谢,这道美味的意大利面非常有帮助...=P(我的整个代码库都是这个项目的“旧意大利面条风格” - 我需要更新自己一些...=) 你刚刚添加了一个 SQL 注入:-P @Lizzan 加入允许字段名称的白名单,否则你会遇到麻烦 @Col。弹片:你怎么能在这里打针?我已经明确表示绝对需要允许列的白名单(请参阅评论,它超出了答案的范围以显示如何做到这一点并且它很简单),并且 mysqli_stmt_bind_params 将负责转义。我没有看到任何注射的可能性......【参考方案2】:

我建议切换到 PDO。它像 mysqli 扩展一样内置在 php 中,但语法更简洁,允许您将参数值作为数组传递,您可以轻松地根据需要使用任意数量的元素动态构造。

【讨论】:

谢谢,我会调查 PDO。它是否会自动发送任何参数,或者您可以指定它吗? 你还在写?在您的查询字符串中。它不会为您构建查询。 啊,好吧,那我看不出它对我有什么帮助,因为我仍然需要 100 种不同的查询排列。 PDO 通过允许他在构建查询字符串本身的同时构建要绑定的值数组来提供帮助。使用 mysqli,您可以将多个参数作为多个参数绑定到单个函数调用,当您不知道要提前传递的参数时,这需要一些更混乱的代码。

以上是关于带有几个可选搜索词的参数化查询的主要内容,如果未能解决你的问题,请参考以下文章

将可选参数优化传递到查询中

机器学习 —— 用于超参数随机化搜索的几个分布

带有 LIKE 和 IN 条件的参数化查询

可以将 CNAME 指向带有查询参数的参数化 URL 吗?

MySQL 站点搜索中的参数化查询问题

使用带有 sqlcommandbuilder 的参数化参数 [无数据适配器]