如何以ActiveRecord最小的安全方式插入参数

时间:2012-06-01 13:08:49

标签: ruby-on-rails ruby activerecord aggregate-functions

如何在不冒SQL注入攻击风险的情况下执行此操作?

nearest = Site.minimum('abs(latitude - ' + params[:lat] + ') - abs(longitude - ' + params[:lon] + ')', group: :id)

我试过了:

nearest = Site.minimum(['abs(latitude - ?) - abs(longitude - ?)', params[:lat], params[:lon]], group: :id)

但这似乎不起作用。文档不是很清楚如何实现这一点。

提前致谢!

2 个答案:

答案 0 :(得分:2)

Rails内部使用sanitize_sql_for_conditions来处理占位符。当然,该方法受到保护,因此您无法(干净地)在ActiveRecord模型之外使用它。您可以使用send

来绕过保护范围
nearest = Site.minimum(
  Site.send(:sanitize_sql_for_conditions, [
    'abs(latitude - ?) - abs(longitude - ?)',
    params[:lat].to_f, params[:lon].to_f
  ]
)

或者您可以将该逻辑放在Site类方法中,这样您就可以在没有欺骗的情况下使用sanitize_sql_for_conditions

class Site < ActiveRecord::Base
  def self.whatever_this_is(lat, lon)
    minimum(
      sanitize_sql([
        'abs(latitude - ?) - abs(longitude - ?)',
        lat, lon
      ])
    )
  end
end

然后在你的控制器中:

nearest = Site.whatever_this_is(params[:lat].to_f, params[:lon].to_f)

记下to_f来电。如果您不包含这些内容,则params[:lat]params[:lon]将成为字符串,sanitize_sql_for_conditions将引用它们:

abs(latitude - '11.23') - abs(longitude - '42.6')

您的数据库可能会或者可能不会很高兴看到您尝试从数字中减去字符串,因此最好准确说出您的意思并自行进行类型转换。

答案 1 :(得分:0)

当然,我无法告诉你从上面的例子中想要完成什么,但看起来你可能不正确地使用了将方法名称作为其第一个参数的最小方法。例如:

Site.minimum(:latitude)

如果你想为它添加条件,我想你会想要使用:

Site.where(country: 'USA').group(:id).minimum(:latitude)

同样,此示例不会返回您期望的结果,但它应该更好地解释API的使用方式。