Как очистить исходный SQL в Rails 4
В Rails 3 я мог бы использовать sanitize_sql_array
для дезинфекции необработанного SQL для тех случайных моментов, когда необходим необработанный SQL-запрос. Но это, похоже, было удалено в Rails 4 или не так сильно удалено, но переместилось в ActiveRecord:: Sanitization. Тем не менее, я не могу понять, как называть sanitize_sql_array
сейчас, так что лучший способ дезинформировать raw SQL в Rails 4?
Я хочу пояснить, что я говорю о полном сыром SQL-запросе здесь, а не о моделях Rail. Я знаю, что это не лучшая практика, это именно то, что я должен сделать для этого конкретного запроса, поскольку он не может быть представлен интерфейсом Active Record с помощью Rails (верьте мне, я пробовал).
Вот примерный вызов, который, очевидно, проще, чем выглядит мой запрос:
query = "SELECT * FROM users
LEFT OUTER JOIN posts ON users.id=posts.user_id
AND posts.topic_id = '#{topic.id}'"
# ^- Obviously bad and very vulnerable, this is what we're trying to fix
ActiveRecord::Base.connection.select_all(query)
Ответы
Ответ 1
Если вам действительно нужно написать сырой SQL, вы можете использовать quote
для дезинфекции:
conn = ActiveRecord::Base.connection
name = conn.quote("John O'Neil")
title = conn.quote(nil)
query = "INSERT INTO users (name,title) VALUES (#{name}, #{title})"
conn.execute(query)
Ответ 2
Из Активных записей документации лучший способ дезинформировать SQL-запрос - это избежать, чтобы построить собственный условия как чистые строки, другими словами, вставляет параметры непосредственно в запрос, например:
User.find_by("user_name = '#{user_name}' AND password = '#{password}'")
и вместо этого используйте параметры массива или хэша.
Условия массива:
Client.where("orders_count = ? AND locked = ?", params[:orders], false)
Условия хеширования:
Client.where(is_active: true)
Пример пояснения:
class User < ActiveRecord::Base
# UNSAFE - susceptible to SQL-injection attacks
def self.authenticate_unsafely(user_name, password)
where("user_name = '#{user_name}' AND password = '#{password}'").first
end
# SAFE
def self.authenticate_safely(user_name, password)
where("user_name = ? AND password = ?", user_name, password).first
end
# SAFE
def self.authenticate_safely_simply(user_name, password)
where(user_name: user_name, password: password).first
end
end
Вот несколько ссылок:
Ответ 3
Метод цитаты и другие методы дезинфекции ActiveRecord::Base
устарели и никогда не были частью общедоступного API.
https://github.com/rails/rails/issues/28947
Официальными методами санитарной обработки являются
http://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html