我正在使用safemysql类进行参数化查询https://github.com/colshrapnel/safemysql。 通常,在准备查询时,它是这样的:
$entries = $db->getAll("SELECT * FROM table WHERE age = ?i AND name = ?s ",$age,$name);
这种查询,我事先知道要解析的参数总数是非常直接的,但似乎我堆积在查询中,我不知道我将使用多少参数 - 例如。搜索表单:
我想做的是参数化以下查询:
if($_POST['nameparts']){
$parts = explode(' ',$_POST['nameparts']);
foreach((array)$parts as $part){
$q .= " AND ( `name` LIKE '%".$part."%' OR `firstname` LIKE '%".$part."%' ) ";
}
if($_POST['age'])
$q .= " AND `age` = '".$_POST['age']."' ";
$entries = $dbs->getAll("SELECT * FROM table WHERE 1 = 1 ".$q." ");
有什么建议吗?
答案 0 :(得分:1)
它看起来不像safemysql支持可变数量的占位符(否则您可以与查询并行构建参数数组)。但您可以使用escapeString(...)
之类的方法。它会给你同样的安全水平,但不是那么优雅。例如:
$q .= " AND `age` = ".$dbs->escapeInt($_POST['age')]." ";
答案 1 :(得分:0)
与使用用户提供的数据的任何其他SQL查询一样,要以真正安全的方式处理此问题(或者更确切地说是推迟它所属的工作),use placeholders。
是的,让我们以开始并且不会忽视它 - 如果查询文本包含[用户提供的]数据那么代码在safemysql's(以及安全的SQL使用)租户之一的违反中,以下不必然是真的!
[safemysql]是安全的,因为每个动态查询部分[或“用户数据位”]都通过占位符进入查询。
然后解决方案是使用占位符和数据数组动态构建查询文本 - 但单独。在任何时候都不会将DQL(SQL语法)和数据混合在一起。正是这种分离(以及较低级别的保证)确保在遵循此方法时没有SQL Injection。
$data = array();
$q = "SELECT * FROM table WHERE 1 = 1 ";
if($_POST['nameparts']){
$parts = explode(' ',$_POST['nameparts']);
foreach((array)$parts as $part){
$q .= " AND (`name` LIKE ?s OR `firstname` LIKE ?s )";
$data[] = '%' . $part . '%'; // add one for each replacement
$data[] = '%' . $part . '%';
}
if($_POST['age']) {
$q .= " AND `age` = ?i ";
$data[] = $_POST['age'];
}
}
现在我们将查询文本与占位符和数组绑定。 Yippee,我们几乎就在那里!现在,创建将传递的数组invoke the method supplying an array for the parameters。
$params = array($q);
$params = array_merge($params, $data);
$entries = call_user_func_array(array($dbs, 'getAll'), $params);
并且,完成了!