我正在努力更新网站以避免任何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(带有值而不是?)来检查以确保查询正常工作,并且没有遇到任何错误或警告。
然后我做了一些实验。我认为我将问题缩小到SQL查询的ORDER BY ? ?
部分,因为代码将运行并在第二个?
更改为ASC
或{{1时加载正确的结果并调整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()
来确保这一点,所以我不相信它会在查询中输入不正确的值。
如果有人对我如何能够解决这个问题或出现什么问题有任何建议,我将非常感激。
答案 0 :(得分:0)
order by
的参数之间需要逗号。所以,如果你有两把钥匙,你会这样做:
ORDER BY ?, ?
但您希望第二个是ASC
或DESC
。您不能直接将这些作为参数传递。您可以将它们构建到字符串中,这应该是安全的,因为您只能根据php中的逻辑放入ASC
或DESC
。或者,您可以传入一个字符串并执行:
ORDER BY (CASE WHEN ? = 'DESC' THEN ? END) DESC,
? ASC
当第一个表达式的计算结果为true时,则使用该值。否则,所有值都为NULL
- 第二个子句生效。
答案 1 :(得分:0)
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
对所有行进行排序。所以根本就没有排序,因为每一行都匹配相同的值。