ruby on rails - query - Rails, cómo sanear SQL en find_by_sql
rails sql query (5)
¿Hay una manera de sanear sql en el método de rieles find_by_sql
?
He intentado esta solución: Ruby on Rails: ¿Cómo desinfectar una cadena para SQL cuando no se usa Find?
Pero falla en
Model.execute_sql("Update users set active = 0 where id = 2")
Emite un error, pero se ejecuta el código SQL y el usuario con ID 2 ahora tiene una cuenta deshabilitada.
El simple find_by_sql
tampoco funciona:
Model.find_by_sql("UPDATE user set active = 0 where id = 1")
# => code executed, user with id 1 have now ban
Editar:
Bueno, mi cliente solicitó realizar esa función (seleccionar por sql) en el panel de administración para realizar una consulta compleja (uniones, condiciones especiales, etc.). Así que tengo muchas ganas de encontrar eso.
Segunda Edición:
Quiero lograr que el código SQL ''malo'' no se ejecute.
En el panel de administración puede escribir consulta -> Update users set admin = true where id = 232
y deseo bloquear cualquier comando UPDATE / DROP / ALTER SQL. Solo quiero saber, que aquí SÓLO se puede ejecutar SELECT.
Después de algunos intentos, concluyo que sanitize_sql_array
desafortunadamente no hace eso.
¿Hay una manera de hacer eso en Rails?
Perdón por la confusion..
Aunque este ejemplo es para la consulta INSERT, se puede usar un enfoque similar para las consultas UPDATE. Inserción masiva de SQL sin procesar:
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
Aquí está la referencia al método sanitize_sql_array en ActiveRecord :: Base , genera la cadena de consulta adecuada al escapar de las comillas simples en las cadenas. Por ejemplo, el punch_line "No dejes que te depriman" se convertirá en "No dejes que te depriman".
Hice un pequeño fragmento de esto que puedes poner en los inicializadores.
class ActiveRecord::Base
def self.escape_sql(array)
self.send(:sanitize_sql_array, array)
end
end
Ahora mismo puedes escapar de tu consulta con esto:
query = User.escape_sql(["Update users set active = ? where id = ?", true, params[:id]])
Y puedes llamar a la consulta de la forma que quieras:
users = User.find_by_sql(query)
Prueba esto:
connect = ActiveRecord::Base.connection();
connect.execute(ActiveRecord::Base.send(:sanitize_sql_array, "your string"))
Puedes guardarlo en variable y usarlo para tus propósitos.
Un poco más de propósito general:
class ActiveRecord::Base
def self.escape_sql(clause, *rest)
self.send(:sanitize_sql_array, rest.empty? ? clause : ([clause] + rest))
end
end
¿Este le permite llamarlo tal como lo escribiría en una cláusula where, sin corchetes adicionales, y utilizando un estilo de matriz? o interpolaciones de estilo hash.
User.find_by_sql (["SELECT * FROM users WHERE (name =?)", Params]) Se encuentra en http://blog.endpoint.com/2012/10/dont-sleep-on-rails-3-sql-injection.html