我有一个带有一堆属性的对象,这些属性代表可搜索的模型属性,我想仅使用设置的属性动态创建一个sql查询。我创建了下面的方法,但我相信它容易受到sql注入攻击。我做了一些研究并阅读了rails活动记录查询界面指南,但似乎where条件总是需要一个静态定义的字符串作为第一个参数。我还试图找到一种方法来清理我的方法生成的sql字符串,但似乎没有一种好方法可以做到这一点。
我怎样才能更好地做到这一点?我应该使用where条件还是以某种方式清理这个sql字符串?感谢。
def query_string
to_return = ""
self.instance_values.symbolize_keys.each do |attr_name, attr_value|
if defined?(attr_value) and !attr_value.blank?
to_return << "#{attr_name} LIKE '%#{attr_value}%' and "
end
end
to_return.chomp(" and ")
end
答案 0 :(得分:1)
当您尝试解决错误的问题时,您的方法有点偏差。您正在尝试构建一个字符串以交给ActiveRecord,以便在您只是尝试构建查询时可以构建查询。
当你说出类似的话时:
Model.where('a and b')
与说法相同:
Model.where('a').where('b')
你可以说:
Model.where('c like ?', pattern)
而不是:
Model.where("c like '#{pattern}'")
将这两个想法与self.instance_values
结合起来可以得到类似的结果:
def query
self.instance_values.select { |_, v| v.present? }.inject(YourModel) do |q, (name, value)|
q.where("#{name} like ?", "%#{value}%")
end
end
甚至:
def query
empties = ->(_, v) { v.blank? }
add_to_query = ->(q, (n, v)) { q.where("#{n} like ?", "%#{v}%") }
instance_values.reject(&empties)
.inject(YourModel, &add_to_query)
end
那些假设您已将所有实例变量正确列入白名单。如果你没有,那么你应该。