2014-09-29 8 views
48

Sto provando a scrivere query LIKE.Safe ActiveRecord come query

Ho letto che le stringhe di stringhe pure non sono sicure, tuttavia non sono riuscito a trovare alcuna documentazione che spieghi come scrivere in modo sicuro LIKE Hash Query.

È possibile? Devo difendere manualmente contro SQL Injection?

+0

Eventuali duplicati di [Come fare una query LIKE in Arel e Rails?] (http://stackoverflow.com/questions/4430578/how-to-do-a-like-query-in-arel-and-rails) –

risposta

96

per assicurarsi che la stringa di query viene validato correttamente, utilizzare la matrice o la sintassi di query hash per descrivere le vostre condizioni:

Foo.where("bar LIKE ?", "%#{query}%") 

o:

Foo.where("bar LIKE :query", query: "%#{query}%") 

Se è possibile che l'query potrebbe includere il carattere % quindi è necessario disinfettare query con sanitize_sql_like prima:

Foo.where("bar LIKE ?", "%#{sanitize_sql_like(query)}%") 
Foo.where("bar LIKE :query", query: "%#{sanitize_sql_like(query)}%") 
+0

Questo non riesce a sfuggire '%' nella stringa di query. Non è arbitrario "SQL injection", ma può ancora funzionare in modo imprevisto. –

+0

@ BeniCherniavsky-Paskin: Questo è l'intero punto, non si vuole sfuggire al '%' perché il '%' è parte della sintassi 'LIKE'. Se sei sfuggito a '%', il risultato sarebbe fondamentalmente una normale query '='. – spickermann

+0

A destra, vuoi usare% caratteri jolly nel tuo modello di modello, ma quel modello è parametrizzato con la variabile 'query', e in molti casi vuoi abbinare letteralmente la stringa nella variabile' query', non permettere a 'query' di usare i metacaratteri LIKE . Prendiamo un esempio più realistico di% ...%: le stringhe hanno una struttura simile a un percorso e tu provi ad abbinare '/ users/# {user.name}/tags /%'. Ora se ordino che il mio nome utente sia 'fr% d%', sarò in grado di osservare i tag 'fred' e' frida' ... –

1

Si può fare

MyModel.where(["title LIKE ?", "%#{params[:query]}%"]) 
4

per PostgreSQL sarà

Foo.where("bar ILIKE ?", "%#{query}%") 
15

Usando Arel è possibile eseguire questa query sicuro e portatile:

title = Model.arel_table[:title] 
Model.where(title.matches("%#{query}%")) 
+0

Questa è la soluzione preferibile, dal momento che Arel è sql-db-agnostic e ha una pulizia di input interna. Inoltre è molto più leggibile e coerente per quanto riguarda lo stile di codice, IMHO. –

+0

Come si nega questo? (cioè NON MI PIACE) 'Model.where (title.matches ("% # {query}% "). not)' funziona, sebbene l'SQL generato sia un po 'scomodo: 'WHERE (NON (\' models \ '. \' title \ 'LIKE '% foo%'))' –

+0

Aah ... lo trova. 'Model.where (title.does_not_match ("% # {} interrogazione%"))'. Genera: 'WHERE (\' models \ '. \' Title \ 'NOT LIKE '% foo%')' –