使用 mysqli prepare with ORDER BY 的问题

Issues using mysqli prepare with ORDER BY

我正在努力更新网站以避免任何 MySQL 注入攻击的机会。这导致我将 mysqli 与 Php.

一起使用

我现在尝试在网站上执行搜索时遇到此错误:

Fatal error: Call to a member function bind_param() on a non-object in ...

搜索旨在从文本框中获取用户输入并在数据库中搜索包含用户输入的特定字符串的记录。我尝试运行的代码如下:

$sql = "SELECT * FROM periodicals WHERE MATCH(author, title, type, keyword, citation) AGAINST (? IN BOOLEAN MODE) ORDER BY ? ? LIMIT ?,?";

$stmt = $conn -> prepare($sql);

$stmt -> bind_param("sssii", $param1, $param2, $param3, $param4, param5);

$param1 = $trimmed; //contains a keyword entered by user to search for
$param2 = $column;  // contains which column to sort by (selected by user)
$param3 = $sort;    // contains 'ASC' or 'DESC' for sorting (selected by user)
$param4 = (empty($s)) ? 0 : $s; //contains offset for LIMIT
$param5 = $limit; // contains number of values to retrieve

我使用了var_dmup($stmt),它返回了false,这意味着对prepare()的调用没有成功。

我读到不正确的 sql 查询可能会导致此错误,并通过 运行 对 sql 进行检查以确保查询正常工作(使用值而不是?' s) 直接在数据库上,没有遇到任何错误或警告。

然后我做了一些实验。我想我将问题缩小到 SQL 查询的 ORDER BY ? ? 部分,因为代码将 运行 并在第二个 ? 更改为 ASC or DESCbind_param() 调整匹配如下:

$sql = "SELECT * FROM periodicals WHERE MATCH(author, title, type, keyword, citation) AGAINST (? IN BOOLEAN MODE) ORDER BY ? DESC LIMIT ?,?";

$stmt = $conn -> prepare($sql);

$stmt -> bind_param("ssii", $param1, $param2, $param4, param5);

$param3 的值在代码前面设置为 DESCASC。在编写将值存储到 $sort 的代码时,我在测试中使用 var_dump() 来确保这一点,因此我不认为它向查询提供了不正确的值。

如果有人对我如何解决这个问题或出了什么问题有任何建议,我将不胜感激。

order by 的参数之间需要一个逗号。所以,如果你有两把钥匙,你会这样做:

ORDER BY ?, ?

但是您希望第二个是 ASCDESC。您不能将它们作为参数直接传递。您可以将它们构建到字符串中,这应该是安全的,因为您只会根据 php 中的逻辑放入 ASCDESC。或者,您可以传入一个字符串并执行:

ORDER BY (CASE WHEN ? = 'DESC' THEN ? END) DESC,
         ? ASC

当第一个表达式的计算结果为真时,您将使用该值。否则,所有值都是 NULL -- 并且第二个子句生效。

bind_param是用来防止SQL Injection的,大家知道的。它通过确保您只能输入值而不能更改实际的 SQL 语句来做到这一点。

如果您尝试输入 ASCDESC 作为参数,您会发现它无法完成。仅仅是因为这意味着您正在更改 SQL 语句。

您应该自己检查值并在查询中输入它。

<?php
$ascOrDesc = ($uservalue=="DESC") ? "DESC" : "ASC";
$sql = "SELECT * FROM periodicals WHERE MATCH(author, title, type, keyword, citation) AGAINST (? IN BOOLEAN MODE) ORDER BY ? " . $ascOrDesc;
?>

请记住,如果您使用 ? 作为 ORDER BY class 中的列名称,您实际上并未按该列值排序。

如果您输入 Name 作为列,您将按值 'name' 而不是列 name 对所有行进行排序。所以根本没有排序,因为每一行都与相同的值匹配。