动态预准备语句不好吗? (使用 php + mysqli)
我喜欢动态 SQL 的灵活性,也喜欢准备语句的安全性和改进的性能。 所以我真正想要的是动态准备语句,这做起来很麻烦,因为bind_param和bind_result接受“固定”数量的参数。 所以我使用 eval() 语句来解决这个问题。 但我感觉这是一个坏主意。 这是我的意思的示例代码
// array of WHERE conditions
$param = array('customer_id'=>1, 'qty'=>'2');
$stmt = $mysqli->stmt_init();
$types = ''; $bindParam = array(); $where = ''; $count = 0;
// build the dynamic sql and param bind conditions
foreach($param as $key=>$val)
{
$types .= 'i';
$bindParam[] = '$p'.$count.'=$param["'.$key.'"]';
$where .= "$key = ? AND ";
$count++;
}
// prepare the query -- SELECT * FROM t1 WHERE customer_id = ? AND qty = ?
$sql = "SELECT * FROM t1 WHERE ".substr($where, 0, strlen($where)-4);
$stmt->prepare($sql);
// assemble the bind_param command
$command = '$stmt->bind_param($types, '.implode(', ', $bindParam).');';
// evaluate the command -- $stmt->bind_param($types,$p0=$param["customer_id"],$p1=$param["qty"]);
eval($command);
最后一个 eval() 语句是一个坏主意吗? 我尝试通过将值封装在变量名 $param 后面来避免代码注入。
有人有意见或其他建议吗? 有我需要注意的问题吗?
I like the flexibility of Dynamic SQL and I like the security + improved performance of Prepared Statements. So what I really want is Dynamic Prepared Statements, which is troublesome to make because bind_param and bind_result accept "fixed" number of arguments. So I made use of an eval() statement to get around this problem. But I get the feeling this is a bad idea. Here's example code of what I mean
// array of WHERE conditions
$param = array('customer_id'=>1, 'qty'=>'2');
$stmt = $mysqli->stmt_init();
$types = ''; $bindParam = array(); $where = ''; $count = 0;
// build the dynamic sql and param bind conditions
foreach($param as $key=>$val)
{
$types .= 'i';
$bindParam[] = '$p'.$count.'=$param["'.$key.'"]';
$where .= "$key = ? AND ";
$count++;
}
// prepare the query -- SELECT * FROM t1 WHERE customer_id = ? AND qty = ?
$sql = "SELECT * FROM t1 WHERE ".substr($where, 0, strlen($where)-4);
$stmt->prepare($sql);
// assemble the bind_param command
$command = '$stmt->bind_param($types, '.implode(', ', $bindParam).');';
// evaluate the command -- $stmt->bind_param($types,$p0=$param["customer_id"],$p1=$param["qty"]);
eval($command);
Is that last eval() statement a bad idea? I tried to avoid code injection by encapsulating values behind the variable name $param.
Does anyone have an opinion or other suggestions? Are there issues I need to be aware of?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为在这里使用
eval()
是危险的。试试这个:
"SELECT * FROM t1 WHERE p1 = ? AND p2 = ?"
prepare()
call_user_func_array()
调用bind_param()
,传入动态参数数组。代码:
I think it is dangerous to use
eval()
here.Try this:
"SELECT * FROM t1 WHERE p1 = ? AND p2 = ?"
prepare()
on thatcall_user_func_array()
to make the call tobind_param()
, passing in the dynamic params array.The code:
我创建了一个过滤函数,它接收一个数组,一个关联数组,如 $_GET:
在模型类中,我定义了几个属性,包括模式:
然后是一个过滤方法,它接收条件的关联数组:
并且非常适合过滤结果
I made a filter function which recives an array an asociative array like $_GET:
In model class I've defined a couple of properties including the schema:
Then a filter method which recive an asociative arrays of conditions:
And works great to filter results
您实际上并不需要准备好的语句和绑定参数,因为您始终可以使用 mysql_real_escape_string()。 你是对的; 动态生成的 SQL 更加灵活和有价值。
这是一个使用常规 mysql_* 接口的简单示例:
当然,这是一个简单化的示例,要使其有用,您必须对其进行大量构建和改进,但它显示了想法,并且确实非常非常有用。 例如,下面是一个完全通用的函数,用于将新行插入任意表中,其中列填充关联数组中的值,并且完全 SQL 注入安全:
You don't really need prepared statements and bound arguments, because you can always use mysql_real_escape_string(). And you're right; dynamically generated SQL is far more flexible and valuable.
Here's a simple example using the regular mysql_* interface:
Of course, this is a simplistic example, and to make it useful you have to build and refine it a lot, but it shows the ideas and it's really very very useful. For example, here is a completely generic function to insert a new row into an arbitrary table, with the columns filled with the values from an associative array and completely SQL-injection safe: