2008-09-19 9 views
8

Ich habe einige Code, der parametrisierte Abfragen verwendet, um gegen die Injektion zu verhindern, aber ich muss auch in der Lage sein, die Abfrage unabhängig von der Struktur der Tabelle dynamisch zu erstellen. Was ist der richtige Weg, dies zu tun?Parametrisierte SQL-Spalten?

Hier ist ein Beispiel, sagen wir eine Tabelle mit Spalten Name, Adresse, Telefon. Ich habe eine Webseite, wo ich Spalten anzeigen und füllen Sie eine Auswahl Dropdown mit ihnen als Optionen.

Als nächstes habe ich ein Textfeld namens Suche. Dieses Textfeld wird als Parameter verwendet.

Derzeit mein Code sieht ungefähr so ​​aus:

 
result = pquery('SELECT * FROM contacts WHERE `' + escape(column) + '`=?', search); 

Ich erhalte ein ekliges Gefühl von ihm aber. Der Grund, warum ich parametrisierte Abfragen verwende, besteht darin, die Verwendung von escape zu vermeiden. Außerdem ist Escape wahrscheinlich nicht für das Entkommen von Spaltennamen konzipiert.

Wie kann ich sicherstellen, dass dies so funktioniert, wie ich es vorhabe?

Edit: Der Grund, warum ich dynamische Abfragen verlangen, ist, dass das Schema vom Benutzer konfigurierbar ist, und ich werde nicht um etwas hart codiert zu beheben sein.

Antwort

6

Anstatt die Spaltennamen zu übergeben, übergeben Sie einfach einen Bezeichner, den Sie mithilfe einer hartcodierten Tabelle in einen Spaltennamen übersetzen. Das bedeutet, dass Sie sich keine Gedanken darüber machen müssen, ob bösartige Daten weitergegeben werden, da alle Daten entweder juristisch übersetzt oder für ungültig erklärt wurden. Psudoish Code:

@columns = qw/Name Address Telephone/; 
if ($columns[$param]) { 
    $query = "select * from contacts where $columns[$param] = ?"; 
} else { 
    die "Invalid column!"; 
} 

run_sql($query, $search); 
+0

Harte Codierung ist keine Option für mich, danke für den Vorschlag! – Martin

+0

Mein Punkt ist nicht, die Spaltennamen fest zu codieren, aber sie nicht von der Schnittstelle zu übergeben. Sie können die Liste der Spalten dynamisch abrufen und weiterhin dieselbe Lösung verwenden. Machen Sie die Spaltennamen nicht zu einem Teil der übergebenen Daten - das schützt Sie vor SQL-Injection. – zigdon

+0

+1 Ja, ich möchte sagen: Lassen Sie Benutzer Daten eingeben, aber lassen Sie nicht Benutzer Code zur Verfügung stellen. –

0

Der Trick ist, in Ihrem Entkommen und Validierung von Routinen, zuversichtlich zu sein. Ich benutze meine eigene SQL Escape-Funktion, die für Literale verschiedener Typen überladen ist. Nirgendwo füge ich Ausdrücke (im Gegensatz zu zitierten Literalwerten) direkt aus Benutzereingaben ein.

Noch kann es getan werden, empfehle ich eine separate — und strenge — Funktion für die Validierung des Spaltennamens. Lassen Sie es nur eine einzige Kennung, so etwas wie

 
/^\w[\w\d_]*$/ 

Du musst auf Annahmen hinsichtlich des zu übernehmen Sie über Ihre eigenen Spaltennamen machen.

0

Ich verwende ADO.NET und die Verwendung von SQL-Befehlen und SQLParameters zu den Befehlen, die sich um das Escape-Problem kümmern. Wenn Sie also auch in einem Microsoft-Tool-Umgebung sind, kann ich sagen, dass ich diese verwenden sehr sucesfully dynamische SQL zu bauen und noch meine Parameter schützen

viel Glück

0

die Säule auf den Ergebnissen der Basis Make eine weitere Abfrage an eine Tabelle, die die möglichen Schemawerte auflistet. In dieser zweiten Abfrage können Sie die Auswahl fest mit dem Spaltennamen codieren, der zum Definieren des Schemas verwendet wird. Wenn keine Zeilen zurückgegeben werden, ist die eingegebene Spalte ungültig.

0

In Standard-SQL werden Begrenzungsbezeichner in doppelte Anführungszeichen eingeschlossen.Das bedeutet:

SELECT * FROM "SomeTable" WHERE "SomeColumn" = ? 

aus einer Tabelle auswählen, wird mit der gezeigten Sometable Kapitalisierung (keinen Fall umgesetzten Version des Namen) genannt, und wird eine Bedingung an eine Spalte namens SomeColumn mit der gezeigten Kapitalisierung gelten.

Von sich aus ist das nicht sehr hilfreich, aber ... wenn Sie die Escape() - Technik mit doppelten Anführungszeichen auf die über Ihr Webformular eingegebenen Namen anwenden können, können Sie Ihre Abfrage einigermaßen sicher aufbauen.

Natürlich sagten Sie, Sie wollten die Verwendung von Escape vermeiden - und in der Tat müssen Sie es nicht auf die Parameter verwenden, wo Sie das bereitstellen? Platzhalter. Wenn Sie jedoch von Benutzern bereitgestellte Daten in die Abfrage einfügen, müssen Sie sich vor böswilligen Personen schützen.

Verschiedene DBMS bieten verschiedene Möglichkeiten zur Bereitstellung von begrenzten Bezeichnern. MS SQL Server zum Beispiel scheint eckige Klammern [SomeTable] anstelle von Anführungszeichen zu verwenden.

0

Spaltennamen in einigen Datenbanken können Leerzeichen enthalten, was bedeutet, dass Sie den Spaltennamen angeben müssen. Wenn Ihre Datenbank jedoch keine solchen Spalten enthält, führen Sie den Spaltennamen durch einen regulären Ausdruck oder eine Überprüfung vor dem Verbinden aus in die SQL:

if ($column !~ /^\w+$/) { 
    die "Bad column name [$column]"; 
}