背景
我一直在从头开始开发一个内容管理系统。由于经验的原因,它主要是从零开始开发的,但它也将在以后使用。
我用PHP语言开发了一个扩展mysqli
类的DatabaseManager
类。我正在使用它做MySQL查询和连接。我开发的一个函数传递SQL查询字符串(已参数化),后跟要替换的正确值的数组。
TL;DR
长话短说,我使用ReflectionClass
将参数绑定到SQL查询和执行。我很好奇这是一种安全的方法,还是有另一种最适合的方法?
该方法
这是DatabaseManager::do_query()
方法:
function do_query($sql, $values){
if(!isset($this->connect_error)){
$num_vals = count($values);
$i = 0;
$type = "";
while($i < $num_vals){
if(is_int($values[$i]) == true)
$type .= "i";
elseif(is_string($values[$i]) == true)
$type .= "s";
$i++;
}
$i = 0;
while($i < $num_vals){
$values2[$i] = &$values[$i];
$i++;
}
$values2 = array_merge(array($type), $values2);
$expr = $this->prepare($sql);
if($expr != false){
$ref = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($expr, $values2);
$expr->execute();
return "Success";
}else{
$error_string = "Error: Query preparation resulted in an error. ";
$error_string .= $this->error;
__TGErrorHandler(TG_ERROR_DB_PREP);
return $error_string;
}
}
}
通过测试,我没有遇到任何直接的错误,而且它似乎可以阻止SQL注入,使用准备好的语句。但是,这个方法的结构有什么潜在的问题吗?
附注:我正在以一种不同的方式处理SELECT
语句。这将主要处理DELETE
和INSERT
语句。
发布于 2015-10-08 13:09:34
首先,你在正确的轨道上。只有少数人,可能是每一百个PHP用户中就有一个想要使用这样一个有用的功能。
接下来,反射对于这个任务来说是多余的,call_user_func_array()
是一种可行的方法。Even though it's a little tricky,这是一种直接的方式,而反射不是。
最后,关于安全的问题。我将删除自动类型检测,并将所有参数绑定为字符串。这不会有任何坏处,但是如果您碰巧将一个数字与数据库中的字符串进行比较,那么使用您当前的方法,数据库可能会返回奇怪的结果。
这个函数中的错误处理也是有问题的。
发布于 2015-10-08 10:48:33
在这里使用反射没有什么不安全的地方,但这是完全不必要的。您可以使用call_user_func_array
在没有反射的情况下完成完全相同的事情
if ($expr !== FALSE) {
call_user_func_array([$expr, "bind_param"], $values2);
$expr->execute();
...
或者,考虑使用PDO而不是mysqli。PDOStatement::execute()
可以将绑定参数数组作为参数。(另外,使用PDO意味着您的代码可以移植到MySQL以外的数据库!)
https://stackoverflow.com/questions/33002277
复制相似问题