2012-08-06 6 views
8

Diese Abfrage funktioniert, ist aber völlig offen für SQL-Injection:Rails Active entkommen Variable mitmachen Klausel

products = Product.find(pids, 
    :select => 'products.*, P.code', 
    :joins => "left join product_dist_match P on 
    (P.pid = products.pid and P.cid = #{cid})", 
) 

Wie kann ich die cid Variable richtig entkommen? Der Parameter conditions ermöglicht das Format ['foo = ?', bar] für diesen Zweck, aber joins nicht.

Ich möchte nicht find_by_sql verwenden, denn dann müsste ich die Joins und Bedingungen hinzufügen, die Teil des Standardumfangs des Modells sind (das wäre nicht DRY).

Edit: Meine Tabellenstruktur ist im Wesentlichen diese:

products: pid (primary key) 
product_dist_match: pid, cid, code 
customers (not used in the query): cid (primary key) 

Beachten Sie, dass dies eine schreibgeschützte Datenbank, die nur Schienen hat eine begrenzte Beteiligung mit. Ich plane nicht, Modelle für alle Tische aufzustellen; Ich möchte nur eine einfache Abfrage wie oben beschrieben durchführen, ohne mich SQL Injection-Angriffen auszusetzen.

+1

Können Sie Ihre Tabellenstruktur beschreiben? das könnte möglich sein, indem Hash-Bedingungen verwendet werden – davidrac

Antwort

14

Die Antwort, die ich gefunden ist, die .sanitize Methode auf dem Modell zu verwenden:

products = Product.find(pids, 
    :select => 'products.*, P.code', 
    :joins => 'left join product_dist_match P on 
    (P.pid = products.pid and P.cid = ' + Product.sanitize(cid) + ')', 
) 

Wenn Sie eine bessere Lösung finden, bitte posten!

+5

Ich habe dies auf die gleiche Weise erreicht - es scheint ein kleines Manko von ActiveRecord zu sein anzunehmen, dass man keine Bedingungen in den Join aufnehmen möchte, und zwar auf eine sichere Art und Weise! – DaveStephens

+0

Warum können wir die Funktion P.cid = cid nicht in einer WHERE-Klausel verwenden? – Ari53nN3o

+0

@parallelRails Wenn Sie wissen, wie Sie die obige Abfrage mit 'where' anstelle von' left join' umschreiben können und identische Ergebnisse erhalten, schreiben Sie sie als Antwort! –

2

Dies scheint mehr zu sein, was Sie versuchten zu tun.

products = Product.find(pids, 
    :select => 'products.*, P.code', 
    :joins => sanitize_sql_array [ 
     'left join product_dist_match P on P.pid = products.pid and P.cid = ?', 
     cid 
    ]