我有一个查询和两个参数。 uuid 和文本。 NpgsqlParameter 正在将值转换为单引号,这会导致语法错误。
jsonb_path_exists
中必须有双引号。
代码:
var idParam = new NpgsqlParameter("id", NpgsqlDbType.Uuid) { Value = id};
var queryParam = new NpgsqlParameter("q", NpgsqlDbType.Text) { Value = q };
var sql = @"SELECT * FROM ""MyTable""
WHERE jsonb_path_exists(""Value"",
'$[*] ? (@.id == @id && @.text like_regex @q flag ""i"" )')";
var rawSql = Context.MyTable.FromSqlRaw(sql, idParam, queryParam);
如果我将类型设置为
NpgsqlDbType.JsonPath
它可以正常工作但容易受到 sql 注入
var condition = $"'$[*] ? (@.id == \"{id}\" && @.text like_regex \"{q}\" flag \"i\" )'";
var jsonPathParam = new NpgsqlParameter("jsonPath", NpgsqlDbType.JsonPath) { Value = $"({condition})" };
ef core 和 npgsql 版本是 6.0.4
edit:是否有可能在不运行查询的情况下检测到容易受到
queryParam
的 sql 注入攻击
Npgsql 似乎有一个错误,导致它错误地转义 JSON 路径参数。我建议你在他们的 Github repo 上将此作为错误 归档。
要解决它,您可以尝试对参数进行横向连接
var idParam = new NpgsqlParameter("id", NpgsqlDbType.Uuid) { Value = id};
var queryParam = new NpgsqlParameter("q", NpgsqlDbType.Text) { Value = q };
var sql = @"
SELECT t.*
FROM MyTable AS t
CROSS JOIN LATERAL (VALUES
(@id, @q)
) AS v(id, q)
WHERE jsonb_path_exists(
t.Value,
'$[*] ? (@.id == v.id && @.text like_regex v.q flag ""i"")'
);
";
var rawSql = Context.MyTable.FromSqlRaw(sql, idParam, queryParam);