首页 > 解决方案 > mysqli_real_escape_string 删除值

问题描述

运行用于 SQL 注入保护的 DBEscape($data) 函数后,我得到空值。有人可以帮忙吗?

我的输入都是多个数组,例如:name="quote[][dt_flight]"、name="quote[][acft]" 等。

方法是 POST。

function DBEscape($data){
    $link = DBConect();
    if(!is_array($data)){
        $data = mysqli_real_escape_string($link,$data);
    }
    else {
        $arr = $data;
        foreach ($arr as $key => $value){
            $key = mysqli_real_escape_string($link, $key);
            $value = mysqli_real_escape_string($link, $value);
            $data[$key] = $value;
        }
    }
    DBClose($link);
    return $data;
}



    function DBCreate($table, array $data, $insertId = false){
        $table = DB_PREFIX.'_'.$table;
        $data = DBEscape($data);
        var_dump($data);
        $fields = implode(", ", array_keys($data));
        $values = "'".implode("', '", $data)."'";
        $query = "INSERT INTO {$table} ({$fields}) VALUES ({$values});";
        var_dump($query);
        return DBExecute($query, $insertId);
    }


if(isset($_POST["quote"]) && is_array($_POST["quote"])){
    foreach($_POST["quote"]["dt_flight"] as $key => $text_field){
        
        $last_id = DBCreate('quote',$_POST['quote'],true);
       
       $i++;
    }  
}

该连接有效,因为它将行插入到表中。我在 DBEscape 之前和之后使用了 vardump 来确定它正在删除值,键很好。

PS:建议的答案是针对单个变量而不是数组。

标签: phpdatabasemysqli

解决方案


正如您在var_dump-result 中看到的那样,您发送到的数据DBCreate因此DBEscape看起来像

array(
    'dt_flight' => array(0 => '2018-06-13'),
    'acft'      => array(0 => 'VQ-BFD',
    // and so on
)

因此,您发送到的数据

// $value = array(0 => '2018-06-13') here
$value = mysqli_real_escape_string($link, $value);

好吧,mysqli_real_escape_string不太喜欢数组,因此会返回NULL并在表中插入空数据。

您很可能希望在foreach($_POST["quote"]["dt_flight"])循环中解决此错误,因为我想您发送了多个航班数据:

foreach($_POST["quote"]["dt_flight"] as $key => $text_field) {
    // $key would be 0, for $_POST["quote"]["dt_flight"][0] = '2018-06-13'

    $keyData = [];
    foreach($_POST["quote"] as $field => $allFieldValues) {
        // Walk over every field, and add the value for the same $key
        if (is_array($data) && isset($allFieldValues[$key])) {
            // Would add for example $keyData['acft'] = $_POST['quote']['acft'][0] = 'VQ-BFD';
            $keyData[$field] = $allFieldValues[$key];
        }
    }

    var_dump($keyData); 
    // Would look like array(
    //    'dt-flight' => '2018-06-13',
    //    'acft'      => 'VQ-BFD',
    //    and so on
    // )

    $last_id = DBCreate('quote',$keyData,true);

    $i++;
}

尽管这不是您问题的一部分,但我真的建议您也注意我对您的问题的评论,mysqli_real_escape_string即不是一种安全的方式来逃避列名(或表名等)。例如使用以下解决方案:

function DBCreate($table, array $data, $insertId = false) {
    // For each table the known columns
    $columns = array( 'quote' => array('dt_flight', 'acft', '...') );

    // Verify valid table given
    if (!isset($columns[$table])) {
        throw new InvalidArgumentException('No such table: ' . $table);
    }

    // Remove everything from data where the key is not in $columns[$table] 
    // = Remove everything where the column-name is non-existing or even an attempt to hack your system
    $data = array_intersect_key($data, array_fill_keys($columns[$table], null));

    if (!count($data)) {
        throw new InvalidArgumentException('No (valid) data given at all');
    }

    // Next, continue with your implementation
}

推荐阅读