web-dev-qa-db-fra.com

Comment désinfecter le SQL brut dans Rails 4

Dans Rails 3, je pourrais utiliser sanitize_sql_array pour assainir le SQL brut lors des moments où une requête en SQL brut est nécessaire. Mais cela semble avoir été supprimé dans Rails 4, ou pas tellement supprimé, mais déplacé vers ActiveRecord :: Sanitization. Cependant, je ne sais pas comment appeler sanitize_sql_array maintenant, alors quel est le meilleur moyen d'assainir le SQL brut dans Rails 4?

Je tiens à préciser que je parle ici d'une requête SQL brute complète, sans utiliser les modèles de Rail. Je suis conscient que ce n'est pas la meilleure pratique, c'est ce que je dois faire pour cette requête spécifique car elle ne peut pas être représentée par l'interface Nice ActiveRecord de Rails (faites-moi confiance, j'ai déjà essayé).

Voici un exemple d'appel, ce qui est évidemment plus simple que ce à quoi ressemble ma requête:

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)
15
Colton Voege

Si vous avez vraiment besoin d'écrire du SQL brut, vous pouvez utiliser quote pour le désinfecter:

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)
13
gabrielhilal

Dans les documents Active Record , le meilleur moyen d'assainir une requête SQL est de eviter pour créer nos propres conditions sous forme de chaînes pures. En d'autres termes, insère les paramètres directement dans la requête, comme ceci: 

User.find_by("user_name = '#{user_name}' AND password = '#{password}'")

et utilisez plutôt des conditions de tableau ou de hachage.

Conditions du tableau:

Client.where("orders_count = ? AND locked = ?", params[:orders], false)

Conditions de hachage:

Client.where(is_active: true)

Un exemple clarifiant:

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

Voici quelques références:

0
NickGnd

La méthode quote et les autres méthodes de nettoyage ActiveRecord::Base sont obsolètes et ne faisaient jamais partie de l'API publique.

https://github.com/Rails/rails/issues/28947

Les méthodes officielles de désinfection sont

http://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html

0
lbaeyens