默认情况下,使用以下命令将清理 str 并使其免受 SQL 注入:
User.where(name: str)
User.where('name ILIKE ?', str)
但是,以下代码(直接字符串插值,然后将其提供给 where 方法)使其对 SQL 注入不安全:
User.where("name = '#{str}'")
就你而言,你可以使用ActiveRecord::Base.sanitize(your_string_from_user_input)。它将使用您的数据库适配器转义/引用相关部分,防止 SQL 注入。
在模型中,您可以直接访问sanitize 方法(因为您处于已经从 ActiveRecord::Base 继承的上下文中):
class User < ActiveRecord::Base
def self.search(string)
terms = string.split
searchable_columns = [:name, :username, :whatever]
query = terms.map do |term|
fields = searchable_columns.map |column|
" #{self.table_name}.#{column} LIKE '#{sanitize("%#{term}%")}'"
end
"(#{fields.join(' OR ')})"
end.join(' AND ')
where(query)
end
end
上面的代码会产生如下的 SQL WHERE 子句:
# str is 'bob doe'
WHERE
(users.name LIKE 'bob' OR users.username LIKE 'bob' OR users.whatever LIKE 'bob')
AND
(users.name LIKE 'doe' OR users.username LIKE 'doe' OR users.whatever LIKE 'doe')