到目前为止,我有以下代码,它根据传递给页面的$ _GET术语显示2个查询。
查询1)根据从$ _GET传递的表名检索列名 - >的工作原理。
查询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;
}
答案 0 :(得分:1)
在SQL中,在准备()查询之前,需要修复所有表名和所有列名以及其他SQL语法。否则,解析不能验证您命名的表实际存在,并且您有足够的权限对其执行操作等。此外,查询优化器可能会决定它当时使用哪些索引(尽管我相信MySQL的情况,优化器在执行()时间之前不会这样做。
因此,您无法参数化表名,列名,表达式,SQL关键字等。
仅在通常使用常量值的位置使用查询参数,例如带引号的字符串文字,引用日期文字或数字常量。
要将表名安全地插入到SQL字符串中,请确保在插入之前白名单该值。也就是说,将表名输入与代码中已知表的列表进行匹配。要么硬编码,要么把它放在配置文件中,要么查询数据库实例以发现存在哪些表。
如果用户输入的字符串与已知存在的字符串不匹配,则必须出错,否则他们会尝试执行SQL注入。无论哪种方式,都不要使用他们的输入。要么使用一些默认的表名,要么给它们一个错误,让他们再试一次。