使用activerecord防止sql注入

时间:2014-06-06 13:30:45

标签: sql ruby activerecord

关于问题how can I use like query in ruby with sinatra?我有以下问题保护我的sql免于注入。这是我从类型字符串进行查询的方法,它接收av(alue)搜索和ak(ey) (=字段)查看。 之后,各种部分由selection.join(' and ')

加入
def string_selector(k, v)
  case
  when v[/\|/]
    v.scan(/([^\|]+)(\|)([^\|]+)/).map {|p| "lower(#{k}) LIKE '%#{p.first.downcase}%' or lower(#{k}) LIKE '%#{p.last.downcase}%'"}
  when v[/[<>=]/]
    v.scan(/(<=?|>=?|=)([^<>=]+)/).map { |part| p part; "#{k} #{part.first} '#{part.last.strip}'"}
  else
    # "lower(#{k}) LIKE '%#{v.downcase}%'" #(works)
    ("lower(#{k}) LIKE ?", '%#{v.downcase}%') #doesn't work
  end
end

但我得到了错误

selectors.rb:38: syntax error, unexpected keyword_end, expecting $end
from C:/../1.9.1/rubygems/core_ext/kernel_require.rb:55:in `require'

我可能做错了什么?

1 个答案:

答案 0 :(得分:1)

如果您使用ActiveRecord,必须有更好的方法来执行您要执行的操作...但是,如果您出于某种原因需要支持string_selector功能,我至少会使用Arel :

def string_selector(k, v)
  tbl = Arel::Table.new(:test) # your table, or you could pass this in...
  condition = case v
  when /\|/
    vals = v.split(/\|/)
    first = vals.shift
    vals.inject(tbl[k].matches("%#{first.strip}%")) do |acc, val|
      acc.or(tbl[k].matches("%#{val.strip}%"))
    end
  when /<>/
    tbl[k].not_eq(v.gsub(/<>/, '').strip)
  when /\=/
    tbl[k].eq(v.gsub(/\=/, '').strip)
  else
    tbl[k].matches(v.strip)
  end
  tbl.where(condition).to_sql
end

请注意,matches会为您执行不区分大小写的查询(例如,在PostgreSQL中使用ILIKE)。