代码之家  ›  专栏  ›  技术社区  ›  DavidC

Rails ActiveRecord:如何在jsonb上使用带双引号的绑定变量

  •  6
  • DavidC  · 技术社区  · 6 年前

    我有一个postgres jsonb查询,如下所示:

    Blog.where("upload_data @> '[ { \"name\": \"#{name}\" }]'")
    

    它工作正常,但破坏了构建,因为优秀的brakeman指出了可能的sql注入风险。如果使用绑定变量:

    Blog.where("upload_data @> '[ { \"name\": ? }]'", name)
    

    它创建一个sql查询,如:

    WHERE upload_data @> '[ { "name": 'name' }]'
    

    请注意单引号-这是一个无效的查询

    如果我使用单引号,我会得到:

    WHERE upload_data @> "[ { 'name': 'name' }]"
    

    这是无效的

    我尝试了其他一些方法,但我想让bind变量计算为带双引号的字符串:

    WHERE upload_data @> '[ { "name": "name" }]'
    

    或者另一种解决方案,而不是让brakeman跳过文件。

    1 回复  |  直到 6 年前
        1
  •  9
  •   Bill Karwin    6 年前

    不能将参数占位符放在带引号的字符串中。

    Rails允许您这样做,并在单引号字符串中替换单引号字符串,这表明Rails无法(像往常一样)理解SQL规则。

    但您可以将参数占位符与其他字符串一起放入表达式中。我不是一个普通的PostgreSQL用户,但我假设您可以将字符串连接在一起,形成一个完整的JSON文本:

    Blog.where("upload_data @> '[ { \"name\": \"' || ? || '\"}]'", name)
    

    您可能会发现,如果将整个JSON值参数化,代码会更加清晰。使用 %Q() 避免需要反斜杠双引号。

    Blog.where("upload_data @> ?", %Q([ { "name": "#{name}" } ]))
    

    或者,为了确保生成有效的JSON,我将表达式放在Ruby语法中,然后转换为JSON:

    Blog.where("upload_data @> ?", JSON.generate( [{name: name}] ))