2011-08-22 13 views
16

C'è un modo per disinfettare il metodo sql in rails find_by_sql?Rails, come disinfettare SQL in find_by_sql

ho provato questa soluzione: Ruby on Rails: How to sanitize a string for SQL when not using find?

ma non riesce a

Model.execute_sql("Update users set active = 0 where id = 2") 

Si genera un errore, ma viene eseguito il codice SQL e l'utente con ID 2 ora ha un account disabilitato.

semplice find_by_sql anche non funziona:

Model.find_by_sql("UPDATE user set active = 0 where id = 1") 
# => code executed, user with id 1 have now ban 

Edit:

Beh il mio cliente chiesto di fare quella funzione (selezionare da SQL) nel pannello di amministrazione per fare qualche query complessa (unisce, condizioni speciali ecc.). Quindi voglio davvero trovarlo.

Secondo Edit:

voglio ottenere che non sarà eseguito il codice SQL 'male'.

Nel pannello di amministrazione è possibile digitare query ->Update users set admin = true where id = 232 e si desidera bloccare qualsiasi comando SQL UPDATE/DROP/ALTER. Voglio solo sapere, che qui puoi SOLO eseguire SELECT.

Dopo alcuni tentativi concludo lo sanitize_sql_array sfortunatamente non lo faccio.

C'è un modo per farlo in Rails ??

Ci scusiamo per la confusione ..

risposta

13

Prova questa:

connect = ActiveRecord::Base.connection(); 
connect.execute(ActiveRecord::Base.send(:sanitize_sql_array, "your string")) 

è possibile salvarlo in variabile e utilizzare per i vostri scopi.

+0

Risultato: 'metodo protetto 'sanitize_sql_array' chiamato per ActiveRecord :: Base: class' –

+1

Ho aggiornato il mio post. Spero che ti possa aiutare – bor1s

+0

.. o puoi usare questo: 'ActiveRecord :: Base.send (: sanitize_sql_array," la tua stringa ")' – bor1s

9

Ho creato un piccolo frammento per questo che è possibile inserire negli inizializzatori.

class ActiveRecord::Base 
    def self.escape_sql(array) 
    self.send(:sanitize_sql_array, array) 
    end 
end 

In questo momento si può sfuggire la query con questo:

query = User.escape_sql(["Update users set active = ? where id = ?", true, params[:id]]) 

E si può chiamare la query come più ti piace:

users = User.find_by_sql(query) 
+2

Questo funzionerà, ma solo un avviso , non avrai bisogno di "inviare". La chiamata di un metodo protetto è consentita dal ricevente quando il chiamante è della stessa classe. Cioè, avrai solo bisogno che la definizione del metodo sia: "def self.escape_sql (obj); sanitize_sql_array obj; fine;" (punto e virgola utilizzato poiché i commenti SO in basso consentono le righe di ritorno) –

+0

[Ho trovato questo rilevante per quanto riguarda un'alternativa all'applica patch] (https://stackoverflow.com/a/2329394/673826) – mlt

+0

Grazie per l'aggiunta e l'esempio su come usarlo. –

8

Leggermente più general-purpose:

class ActiveRecord::Base 
    def self.escape_sql(clause, *rest) 
    self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest)) 
    end 
end 

Questo ti consente di chiamalo come se dovessi digitare una clausola where, senza parentesi e usare uno stile array? o interpolazioni stile hash.

+0

Grazie, ha funzionato perfettamente. Solo aggiungendo che questo va nel inizializzatore. – KPheasey

1

Sebbene questo esempio sia per la query INSERT, è possibile utilizzare un approccio simile per le query UPDATE.Raw inserimento di massa SQL:

users_places = [] 
users_values = [] 
timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S') 
params[:users].each do |user| 
    users_places << "(?,?,?,?)" # Append to array 
    users_values << user[:name] << user[:punch_line] << timestamp << timestamp 
end 

bulk_insert_users_sql_arr = ["INSERT INTO users (name, punch_line, created_at, updated_at) VALUES #{users_places.join(", ")}"] + users_values 
begin 
    sql = ActiveRecord::Base.send(:sanitize_sql_array, bulk_insert_users_sql_arr) 
    ActiveRecord::Base.connection.execute(sql) 
rescue 
    "something went wrong with the bulk insert sql query" 
end 

Ecco l'reference to sanitize_sql_array method in ActiveRecord::Base, genera la stringa di query corretta fuggendo le virgolette singole nelle stringhe. Ad esempio la punch_line "Non lasciarti abbattere" diventerà "Non lasciare che ti buttino giù".

Problemi correlati