我正在尝试创建一个允许我删除表中某一行的函数。我想将函数用于几个不同的表,所以当我调用函数时,我会将函数的一个参数作为表名。以下是我正在尝试做的一个例子:
function delete($conn, $table, $id) {
$stmt = $conn->prepare("DELETE FROM ".$table." WHERE id = :id");
$stmt->bindParam(":id", $id, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() > 0) {
return true;
} else {
return false;
}
}
我遇到的一个问题是,因为$ table变量直接进入SQL查询,我的数据库不会受到SQL注入的风险吗?
当我从其他一个问题中学习时,我不能只放:table并将其添加到bindParam函数中,所以我不知道如何使这个函数安全。任何想法??
答案 0 :(得分:3)
您可以定义要在函数中使用的列入白名单的表名列表:
$whitelist = array('table1', 'table2', ...)
然后使用:
$myTable= array_intersect_keys($table, array_flip($whitelist));
$myTable
现在将是安全的。
答案 1 :(得分:0)
作为元数据的表名比行数据更受限制 - 因此清理表名应该比清理数据更可靠。通过这种方式,我可以在PDO之外进行消毒。
我们经常使用的是PHP include,它包含所有有效的表名作为数组定义,因此我们只需查找它 - 如果找不到它,并且include的文件年龄超过一小时,我们运行“SHOW TABLES”并重新创建包含,因此它非常自动化。
答案 2 :(得分:0)
MySQL目前不支持动态SQL字符串构建,但您可以尝试使用PDO准备好的语句(可能是冗余的,我知道的)表的白名单或可能的MySQL预处理语句。
$sql = "
PREPARE stmt FROM
'DELETE FROM @tbl WHERE id = :id';
EXECUTE stmt USING :table;
";
$stmt = $db->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':table', $table);
这是未经测试的,但可能有所帮助。