php - 如何动态准备 SQL 查询(列名也是如此)避免 SQL 注入(inject)

标签 php html mysqli sql-injection bindparam

我最近了解了 SQL 注入(inject)以及使用 prepare()bind_param() 避免 SQL 注入(inject)的 PHP 建议。 现在,我想动态准备 SQL 查询,添加列名称和值。

我过去常常这样做,让 HTML 输入的 name 字段与 MySQL 数据库列的名称相同。

    <input type="text" name="firstname" >
    <input type="text" name="lastname" >

然后,使用 mysqli 动态创建 SQL 查询。

    // Extract values from POST
    $parameters = $_POST;
    // Organize the values in two strings
    foreach ($parameters as $id => $value) {
        $fields = $fields . "`" . $id . "`,";
        $values = $values . "'" . $value . "',"; 

        /*e.g.
            $fields = `firstname`,`lastname`
            $values = 'John','Wick'
        */
    }

    // Write into the database
    $sql = "INSERT INTO `user` ($fields) VALUES ($values)";

    /*e.g.
        INSERT INTO `user` (`firstname`,`lastname`) VALUES ('John','Wick')
    */

我想知道是否有办法使用 prepare()bind_param() 来避免 SQL 注入(inject),可能会添加一些 data-type="s" 到 HTML 输入标记,或者是否有更好、更多最佳实践的方法。

最佳答案

您只能将绑定(bind)参数用于常量值元素——带引号的字符串、带引号的日期时间或数字文字。

您不能将参数占位符用于 SQL 中的任何其他内容,例如列名、表名、值列表、SQL 关键字或表达式或其他语法。

如果您需要使列名称动态化,唯一的选择是根据已知列的列表来验证它们。

$columns_in_user_table = [
  'userid'=>null,
  'username'=>'',
  'firstname'=>'',
  'lastname'=>''
];
// Extract values from POST, but only those that match known columns
$parameters = array_intersect_key($_POST, $columns_in_user_table);
// Make sure no columns are missing; assign default values as needed
$parameters = array_merge($columns_in_user_table, $parameters);

如果您使用 PDO 而不是 mysqli,则可以跳过绑定(bind)。只需使用命名参数,并将列值对的关联数组直接传递给 execute():

$columns = [];
$placeholders = [];
foreach ($parameters as $col => $value) {
    $columns[] = "`$col`";
    $placeholders[] = ":$col";
}
$column_list = implode($columns, ',');
$placeholder_list = implode($placeholders, ',');

// Write into the database
$sql = "INSERT INTO `user` ($column_list) VALUES ($placeholder_list)";

$stmt = $pdo->prepare($sql);
$stmt->execute($parameters);

关于php - 如何动态准备 SQL 查询(列名也是如此)避免 SQL 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55504949/

相关文章:

php - 使用 PDO 发送空值会导致错误

php - 为什么我在使用 w3school 教程时遇到错误?

php - 从 SQL 数据库下载文件时出现错误

php - 在 PhpStorm 中代码完成时是否有插入 PHP 对象运算符的快捷方式?

php - HTML5 - 共享主机中的 WebSocket

javascript - 使用 jQuery 在回发时设置 img src

javascript - 引用错误文档未在 javascript 中定义

javascript - 错误 : Failed to instantiate module restangular due to: '_' is undefined

php - 多个mysqli对象相互覆盖

php - 我可以获得除一个之外的所有 $_POST 数据