使用PHP的Reflection Class来安全执行MySQL查询吗?

时间:2015-10-07 20:57:00

标签: php mysql class security mysqli

背景

我一直在从头开发内容管理系统。由于经验原因,它主要是从零开始开发的,但它也将在未来使用。

我开发了一个DatabaseManager类,它扩展了PHP中的mysqli类。我正在使用它做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注入。但是,这种方法的结构是否存在潜在问题?

P.S。我以不同的方式处理SELECT语句。这将主要处理DELETEINSERT语句。

2 个答案:

答案 0 :(得分:1)

首先,你走在正确的轨道上。只有少数,可能是百分之一的PHP用户甚至想到使用这样一个有用的功能。

接下来,反射对于此任务来说是多余的,call_user_func_array()是一种方法。 Even though it's a little tricky,这是一种直截了当的方式,而反思则不是。

最后,对安全。我会删除自动类型检测并将所有参数绑定为字符串。它不会造成任何伤害,而使用您当前的方法,如果您碰巧将数字与数据库中的字符串进行比较,则数据库可能会返回奇怪的结果。

此功能中的错误处理也值得怀疑。

答案 1 :(得分:0)

在这里使用反射并没有什么固有的不安全感,但这完全没必要。你可以使用call_user_func_array完成完全相同的事情而无需反思:

if ($expr !== FALSE) {
    call_user_func_array([$expr, "bind_param"], $values2);
    $expr->execute();
    ...

或者,考虑使用PDO而不是mysqli。 PDOStatement::execute()可以将一组绑定参数作为参数。 (另外,使用PDO意味着您的代码可以移植到MySQL以外的数据库!)