我习惯使用参数化语句,但在此语句中,参数的数量可能会根据搜索字符串中的单词数而变化。
所以“食物”= 1个参数,“一些食物”= 2,“大量食物”= 3等等
我基本上设置了一个查询,允许搜索网站,改进功能,我可以搜索列的某些单词而不必完美匹配。
例如,我将俱乐部名称及其城市联合起来;
名称:薄荷俱乐部,
城市:利兹
上校:利兹铸币局
搜索:'Mint Leeds'通常会导致找不到行。但是通过这种修改,它可以工作。
使用未知数量的参数我基本上想知道如何保护我的语句,因为我认为它仍然对sql注入开放。
以下代码:
$keystring = $mysqli->real_escape_string($_POST["s"]);
$key = strtoupper($keystring);
$key_arr = explode(" ", $key);
$num_key = count($key_arr);
if($num_key >= 2){
$where = '';
foreach($key_arr as $val){
$where .= "(CONCAT(name,' ',city) LIKE '%".$val."%') AND ";
}
$where = substr($where, 0, -4);
$clubWhere = $where;
}
else{
$key = "%".$key."%";
$clubWhere = "(CONCAT(name,' ',city) LIKE '".$key."')";
}
$search_stmt = $mysqli->prepare("SELECT id, name, type AS 'col3', city AS 'col4', 'Club' AS 'table' FROM studentnights_clubs WHERE ".$clubWhere."
UNION
SELECT id, name, description AS 'col3', image AS 'col4', 'Event' AS 'table' FROM studentnights_events WHERE UCASE(name) LIKE ?
UNION
SELECT id, name, '' AS 'col3', '' AS 'col4', 'Genre' AS 'table' FROM studentnights_music WHERE UCASE(name) LIKE ?
ORDER BY
CASE
WHEN name LIKE ? THEN 1
WHEN name LIKE ? THEN 3
ELSE 2
END
LIMIT 10");
$search_stmt->bind_param('ssss', $key, $key, $key, $key);
$search_stmt->execute();
$search_stmt->store_result();
$search_stmt_num = $search_stmt->num_rows;
$search_stmt->bind_result($id, $name, $col3, $col4, $table);
答案 0 :(得分:1)
像这样的东西(删除所有无用的分支),
$where = '';
$values = array();
foreach(explode(" ", $key) as $val)
{
$values[] = "%$val%";
$where .= "(CONCAT(name,' ',city) LIKE ?) AND ";
}
$where = substr($where, 0, -4);
然后将其他值添加到$ values数组
$values[] = $key;
$values[] = $key;
$values[] = $key;
$values[] = $key;
然后使用动态绑定,如此处所述https://stackoverflow.com/a/17874410/285587
答案 1 :(得分:-1)
您的$val
和$key
项是用户提供的搜索参数,因此您需要确保其中的垃圾无法通过查询。
一种可能性:准备两个不同的SQL语句,并使用具有适当数量的绑定变量的语句。
另一个:在使用它们构造SQL语句之前清理传入的字符串。您说他们会放置名称,例如'newcastle-upon-tyne'
,'denver'
或'new york'
。例如,它们可能不是'new ; drop table super_users;'
。
所以在这里你可以如何消毒它们。
$val = $mysqli->real_escape_string(preg_replace('[^- A-Za-z0-9]', '', $val ));
这行代码将消除$val
中的所有字符,但字母,数字,空格和短划线除外。然后它会将转义符放入字符串中以对mysqli进行清理。
如果您预处理'new ; drop table super_users;'
,您将获得'new drop table superusers'
,这对于查询来说足够安全,尽管毫无意义。
您还可以在用户提供的搜索字词中查找禁用的字符,如果存在,则拒绝进行搜索。
看,我们都知道使用绑定变量更安全,但是如果你不能,你仍然可以清理东西。