避免 sql 注入 connection.execute

Avoid sql injection with connection.execute

如果无法使用 ActiveRecord 有效地表达查询,如何在插入传递的 params 属性时安全地使用 ActiveRecord::Base.connection.execute

connection.execute "... #{params[:search]} ..."

ActiveRecord 有一个 sanitize 方法,允许您首先清理查询。 也许您可以研究一下:http://apidock.com/rails/v4.1.8/ActiveRecord/Sanitization/ClassMethods/sanitize

尽管如此,我会非常小心地直接插入参数。 您遇到什么问题,无法使用 ActiveRecord?

您可以使用ActiveRecord::Sanitization::ClassMethods中的方法。

您必须稍微小心,因为它们受到保护,因此仅供 ActiveRecord::Base subclasses 使用。

在模型中 class 你可以这样做:

class MyModel < ActiveRecord::Base

  def bespoke_query(params)
    query = sanitize_sql(['select * from somewhere where a = ?', params[:search]])
    connection.execute(query)
  end

end

您也可以send在控制台上尝试的方法:

> MyModel.send(:sanitize_sql, ["Evening Officer ?", "'Dibble'"])
=> "Evening Officer '\'Dibble\''"

您可以使用 ActiveRecord::Base 中的函数来清理您的 sql 查询。例如。 sanitize_sql_array。正如其他答案中提到的那样,它们受到保护,但是无需处理继承就可以绕过。

sanitize_sql_array 接受字符串数组,其中第一个元素是查询,后续元素将替换查询中的 ? 个字符。

query = 'SELECT * FROM users WHERE id = ? OR first_name = ?'
id = 1
name = 'Alice'

sanitized_query = ActiveRecord::Base.send(:sanitize_sql_array, [query, id, name])
response = ActiveRecord::Base.connection.execute(sanitized_query)