传递键值对是否也可以防止 SQL 注入攻击?

Does passing in key value pairs also protect against SQL injection attacks?

我遇到了这个示例,其中没有使用绑定参数,而是将键值对传递给了 heredoc。我知道这将允许用户以任何顺序输入,但我的问题是,如果我使用键值对而不是绑定参数,它是否仍能免受 SQL 注入攻击?如果没有,有没有办法允许用户在没有任何特定顺序的情况下传递输入,同时还可以防止注入攻击?

下面是使用键值对的例子:

def self.find_by_id(id)
    found_user = QuestionDatabase.instance.execute(<<-SQL, id: id)
      SELECT
        users.*
      FROM
        users
      WHERE
        users.id = :id
    SQL
    found_user.nil? ? nil : User.new(found_user)
  end

这里是使用绑定参数的例子:

def self.find_by_id(id)
    found_user = QuestionDatabase.instance.execute(<<-SQL, id)
      SELECT
        users.*
      FROM
        users
      WHERE
        users.id = ?
    SQL
    found_user.nil? ? nil : User.new(found_user)
  end

据我所知,没有将参数传递给 heredoc 的语法。您所展示的实际上只是将散列作为参数传递给 execute().

Ruby 允许参数是标量或数组或散列。

require 'pp'

def execute(sql, binds)
        pp binds
end

id = 123

execute('blah blah blah', id: id)

execute('blah blah blah', id)

输出:

{:id=>123}
123

它实际上并没有将 id 与字符串结合起来,它只是将其作为参数传递给 execute() 函数。第一次,它传递一个散列,所以你得到关联的键值对。第二次,只是传递一个标量。

大概真正的 Rails execute() 方法有一些代码来检查传递的参数是标量还是散列,然后它从 [=31= 中解析命名参数占位符] 字符串,如果您使用的 RDBMS 不支持命名参数,它将用 ? 占位符替换它们。

无论如何,SQL 注入都是安全的。