为了防止 SQL 注入,为查询准备动态 MySQL JSON 选择器的最佳/正确方法是什么?举个例子,假设我想执行以下查询:
SELECT `key` ->> "$.key.path" AS `setting_value`
FROM `settings`
LIMIT 1
但我想让关键路径动态化,例如:
$sql = <<<SQL
SELECT `key` ->> "{$path}" AS `setting_value`
FROM `settings`
LIMIT 1
SQL;
通过条件值,我可以使用 PDO 为准备好的语句构建 SQL,例如:
$sql = <<<SQL
SELECT *
FROM `settings`
WHERE `other_field` = :field_val
LIMIT 1
SQL;
$statement = $this->handle()->prepare($sql);
$statement->execute([':field_val' => 'some val']);
$records = $statement->fetchAll(PDO::FETCH_OBJ);
向我的数据库适配器(甚至我的辅助函数)添加类似以下内容似乎相当不优雅并且容易出现错误/问题:
public function cleanJsonSelector(string $selector) : string {
return preg_replace('/[^-\$a-zA-Z0-9_\[\].*\s]/', '', $selector);
}
想法/帮助?
->
和->>
运算符仅支持字符串文字。它们没有表达式、变量或参数。
但是您可以在等效的 JSON 函数中使用任何表达式(包括参数占位符)
JSON_EXTRACT()
。
->>
运算符就像JSON_UNQUOTE(JSON_EXTRACT(json_doc, path))
$sql = <<<SQL
SELECT JSON_UNQUOTE(JSON_EXTRACT(`key`, :path)) AS `setting_value`
FROM `settings`
LIMIT 1
SQL;
这似乎是 MySQL JSON 运算符功能中不必要的不一致,但这就是当前 MySQL 8.3 版本中的实现方式。