我正在努力更新一个网站,以避免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
或 DESC
并且bind_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
的值设置为代码中较早的DESC
或ASC
。我在测试中使用了var_dump()
来确保在编写将值存储到$sort
的代码时这一点,因此我不认为它会将不正确的值输入到查询中。
如果有人对我如何解决这个问题或出了什么问题有任何建议,我将不胜感激。
bind_param
用于防止SQL Injection
如您所知。它通过确保您只能输入值而不能更改实际的 SQL
语句来实现。
如果您尝试输入ASC
或DESC
作为参数,您会注意到它无法完成。仅仅因为这意味着您正在更改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
类中使用 ?
作为列名,则实际上并不是按该列值排序。
如果输入 Name
作为列,则将按值"name"而不是列name
对所有行进行排序。因此,根本不会有排序,因为每一行都与相同的值匹配。
order by
的参数之间加一个逗号。 因此,如果您有两个密钥,则可以执行以下操作:
ORDER BY ?, ?
但是您希望第二个是ASC
或DESC
. 不能直接将这些参数作为参数传入。 您可以将它们构建到字符串中,这应该是安全的,因为您只会根据 php 中的逻辑放入ASC
或DESC
。 或者,您可以传入一个字符串并执行以下操作:
ORDER BY (CASE WHEN ? = 'DESC' THEN ? END) DESC,
? ASC
当第一个表达式的计算结果为 true 时,使用该值。 否则,所有值都将NULL
-- 并且第二个子句生效。