Sé de sentencias preparadas, pero si uso SQL sin formato, ¿ActiveRecord tiene una forma de escanear valores manualmente?Escapar valores en Rails (similar a mysql_real_escape_string())
Algo como esto sería bueno:
self.escape("O'Malley") # O\'Malley
Sé de sentencias preparadas, pero si uso SQL sin formato, ¿ActiveRecord tiene una forma de escanear valores manualmente?Escapar valores en Rails (similar a mysql_real_escape_string())
Algo como esto sería bueno:
self.escape("O'Malley") # O\'Malley
que puede hacer:
Dude.sanitize("O'Malley")
o
Dude.connection.quote("O'Malley")
ambos con el mismo resultado: => "'O''Malley'"
Incluso con Model.find_by_sql
todavía se puede utilizar la forma en que se interponen en signos de interrogación como valores escapado.
Basta con pasar una matriz en donde el primer elemento es la consulta y elementos sucesivos son los valores que ser sustituido en
Ejemplo de la documentación de Rails API:.
Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
¿Qué pasa si estoy insertando? –
Puedo desenterrarlo, pero realmente: ¿por qué estás insertando fuera de ActiveRelation/ActiveModel? –
Estoy haciendo un 'INSERT IGNORE' y estoy actualizando varios registros en una declaración para el rendimiento. –
Usted puede utilizar fácilmente el mysql2 gema para hacer esto:
irb(main):002:0> require 'rubygems'
=> true
irb(main):003:0> require 'mysql2'
=> true
irb(main):004:0> Mysql2::Client.escape("O'Malley") # => "O\\'Malley"
=> "O\\'Malley"
O si se utiliza el MySQL anterior (no mysql2) joya:
irb(main):002:0> require 'rubygems'
=> true
irb(main):003:0> require 'mysql'
=> true
irb(main):004:0> Mysql.escape_string("O'Malley")
=> "O\\'Malley"
Esto le permitirá escapar de todo lo que desee y luego insertarlo en la base de datos. También puede hacer esto en la mayoría de los modelos en su aplicación de rieles utilizando el método de sanitización. Por ejemplo decir que tienes un modelo llamado Persona. Podrías hacerlo.
Person.sanitize("O'Malley")
Eso debería hacer el truco.
Una inmersión rápida en la fuente de ActiveRecord revela su método "sanitize_sql_array" para la desinfección del tipo de instrucción SQL [string, bind_variable[, bind_variable]]
Se le podría llamar directamente:
sql = ActiveRecord::Base.send(:sanitize_sql_array, ["insert into foo (bar, baz) values (?, ?), (?, ?)", 'a', 'b', 'c', 'd'])
res = ActiveRecord::Base.connection.execute(sql)
Jason: Esta es una solución mejor ya que es independiente de DB. Si la aplicación se implementa en Heroku, la solución actualmente aceptada (@quest) no funcionará. –
Cuatro años después, 'sanitize_sql_array' y sus primos aún no son parte de la API pública. ¿Hay un equivalente público conveniente? –
En caso de que alguien está buscando a un ejemplo más concreto de la solución de @ jemminger, aquí está para inserción masiva:
users_places = []
users_values = []
timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
params[:users].each do |user|
users_places "(?,?,?,?)"
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í es el reference to sanitize_sql_array method in ActiveRecord::Base, genera la cadena de consulta adecuada escapando las comillas simples en las cadenas. Por ejemplo, punch_line "No dejes que te depriman" se convertirá en "No dejes que te depriman".
Si no desea que las cotizaciones adicionales individuales envolviendo su cadena que se produce al utilizar la solución Publicado por @konus, usted puede hacer esto:
Dude.connection.quote_string("O'Malley")
Esto devuelve "O\'Malley"
en lugar de "'O\'Malley'"
Esto no le impedirá SQL inyección. – tvdeyen
@tvdeyen: ¿Estaría dispuesto a ilustrar de qué manera lo anterior sería vulnerable, especialmente en comparación con la respuesta aceptada? En definitiva, 'quote_string' dependerá del adaptador ActiveRecord particular que se utilice. Para el adaptador mysql2 y el adaptador mysql abstracto, 'quote' llama a' quote_string' para valores de cadenas y ajusta el resultado entre comillas. ¿Estás pensando en algún tipo de inyección multibyte o algo más? Gracias. – Nathan
Gracias @Nathan., Funciona para mí .. –
Me encanta tu nombre de modelo. 'Amigo ', eres increíble. –
@NateSymer: Sí, bueno, así es, como, tu opinión, hombre. – Fuser97381
En caso de que alguien más se esté preguntando, sí, son exactamente lo mismo: [desinfectar llamadas connection.quote] (http://apidock.com/rails/ActiveRecord/Base/sanitize/class) – mltsy