php - 我可以在准备好的语句中参数化表名吗?

标签 php mysql sql

<分区>

我已经多次使用 mysqli_stmt_bind_param 函数。但是,如果我将试图防止 SQL 注入(inject)的变量分开,则会遇到错误。

这是一些代码示例:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{
    $statement = $mysqli->prepare("INSERT INTO " .$new_table . " VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'sssisss', $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}

是否有可能以某种方式将 .$new_table. 连接替换为另一个问号语句,制作另一个绑定(bind)参数语句,或添加到现有语句以防止 SQL 注入(inject)?

像这样或这样的某种形式:

function insertRow( $db, $mysqli, $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol )
{    
    $statement = $mysqli->prepare("INSERT INTO (?) VALUES (?,?,?,?,?,?,?);");
    mysqli_stmt_bind_param( $statment, 'ssssisss', $new_table, $Partner, $Merchant, $ips, $score, $category, $overall, $protocol );
    $statement->execute();
}

最佳答案

对您的问题的简短回答是“否”。

从最严格的意义上说,在数据库级别,准备好的语句只允许参数绑定(bind)到 SQL 语句的“值”位。

一种思考方式是“可以在运行时执行语句时替换而不改变其含义的东西”。表名不是这些运行时值之一,因为它决定了 SQL 语句本身的有效性(即,哪些列名有效)并且在执行时更改它可能会改变 SQL 语句是否有效。

在稍微高一点的水平上,即使在模拟准备好的语句参数替换而不是实际将准备好的语句发送到数据库的数据库接口(interface)中,例如 PDO,可以想象它可以允许您在任何地方使用占位符(因为占位符之前被替换在这些系统中被发送到数据库),表占位符的值将是一个字符串,并包含在发送到数据库的 SQL 中,因此 SELECT * FROM ?mytable 因为参数实际上最终会将 SELECT * FROM 'mytable' 发送到数据库,这是无效的 SQL。

你最好的选择就是继续

SELECT * FROM {$mytable}

但是你绝对应该有一个表的白名单,如果 $mytable 来自用户输入,你首先要检查它。

关于php - 我可以在准备好的语句中参数化表名吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37033015/

相关文章:

php - Codeigniter SQL 查询构建

PHP Date - 时差格式化

mysql - 如何根据某些条件将结果分组为串联结果

c# - 为什么 Entity Framework 会在直接sql立即返回时计算语句超时?

php - 使用准备好的语句创建 MySQL 用户?

php - 如何使用 PHP 检查照片 DPI

mysql - SQL 查询抛出错误 150

sql - 在行组之间插入空白行并在sql中按ID排序

php - Ubuntu 上的所有帐户都拒绝 MySQL 访问,但 PHPMyAdmin 工作正常?

javascript - C3JS加载函数和点值