1

到目前为止,我有以下代码,它基于传递给页面的 $_GET 术语进行了 2 个查询。

查询 1) 根据从 $_GET -> Works 传递的表名检索列名。

查询 2) 从该表中检索数据 -> 不起作用。

第二个查询是这样的:

$table_data = db_adminQuery('SELECT * FROM :tbl_name', array(':tbl_name' => $p ));

当我将查询更改为:

$table_data = db_adminQuery('SELECT * FROM events', array());

它有效,但我不明白为什么它一开始就不起作用。如果我遗漏了什么或有一些愚蠢的错误,请告诉我,因为我不知道这有什么问题。

这是完整的来源:

    if(isset($_GET['page']))
    {
        $pages = array('events','news','ads','slider');
        $page = trim($_GET['page']);

        if(in_array($page, $pages))
        {
            include 'db.php';
            administer($page);
        }

    }


    function administer($p)
    {

        /*
        *
        *   TABLE COLUMN NAMES & TYPES
        *
        */

        $columns_tmp = db_adminQuery('SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = \'evented\' AND TABLE_Name = :table_name', array(':table_name' => $p));

        if(!empty($columns_tmp))
        {
            $columns = array();
            foreach ($columns_tmp as $key => $value) 
            {   
                array_push($columns, array('name' => $value['COLUMN_NAME'], 'type' => $value['DATA_TYPE']));
            }
        }

        /*
        *
        *   TABLE DATA
        *
        */

        $table_data = db_adminQuery('SELECT * FROM :tbl_name', array(':tbl_name' => $p ));
        print_r($table_data);

        $table = '<table cellpadding="0" cellspacing ="0">'.PHP_EOL;
        $table .= '<tr>'.PHP_EOL;

        foreach ($columns as $key => $value) 
        {   
            $table .= '<th style="padding:5px;">'.$value['name'].'</th>';
        }

        $table .= '</tr>'.PHP_EOL;

        foreach ($table_data as $data_key => $data_value) 
        {
            $table .= '<tr>'.PHP_EOL;
            //$table .= '<td>'.$data_value.'</td>';
            $table .= '</tr>'.PHP_EOL;
        }

        $table .= '</table>';


        echo $table;    
    }


    function db_adminQuery($query, $params = array(), $return = true)
    {
        global $db;

        if($stmt = $db->prepare($query))
        {
            // PARAMETERS
            if(!empty($params))
            {
                foreach($params as $key => $value) 
                {
                    $stmt->bindParam($key, $value); 
                    echo $key.' - '.$value.'<br>';      
                }
            }

            $stmt->execute();

            if($return == true)
            {
                $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

                return $result;
            }
        }
        return false;
    }
4

1 回答 1

1

在 SQL 中,需要在 prepare() 查询之前修复所有表名和所有列名以及其他 SQL 语法。否则解析无法验证您命名的表是否确实存在,并且您有足够的权限对​​其进行操作等等。查询优化器可能会决定它当时使用哪些索引(尽管我相信 MySQL 的情况,优化器在执行()时间之前不会这样做)。

所以不能参数化表名、列名、表达式、SQL关键字等。

仅在通常使用常量值的地方使用查询参数,例如带引号的字符串文字、带引号的日期文字或数字常量。

要将表名安全地插入 SQL 字符串,请确保在插入之前将该值列入白名单。也就是说,将表名输入与代码中的已知表列表进行匹配。要么对其进行硬编码,要么将其放入配置文件中,要么查询数据库实例以发现存在哪些表。

如果用户输入的字符串与已知存在的内容不匹配,则他们一定犯了错误,否则他们正试图实施 SQL 注入。无论哪种方式,都不要使用他们的输入。要么使用一些默认的表名,要么给他们一个错误,让他们再试一次。

于 2013-03-07T23:21:27.317 回答