2012-10-11 5 views
6

Ich möchte Abfrage-Parameter an cursor.execute() Methode von MySQLdb als benanntes Wörterbuch, so dass sie Eskorted von SQL-Injektion übergeben.Python MySQLdb: Abfrage Parameter als ein benanntes Wörterbuch

Können Sie erklären, warum dies gibt KeyError:

>>>c.execute('select id from users where username=%(user)s', {'user':'bob',}) 
KeyError: 'user' 

MySQLdb Handbuch http://mysql-python.sourceforge.net/MySQLdb.html sagt:

* paramstyle

String Konstante, die die Art der Parametermarkierung eine von der Schnittstelle erwartet Formatierung. Set to 'Format' = ANSI C Druckformatcodes, z. '... WHERE Name =% s'. Wenn ein Mapping-Objekt für conn.Execute() verwendet wird, dann ist die Schnittstelle verwendet tatsächlich ‚pyformat‘ = Python erweiterten Formatcodes, z.B. '... WHERE Name =% (Name) s'. Allerdings ist die API derzeit nicht der Spezifikation von mehr als ein Stil in paramstyle erlauben *

Antwort

6

Die Zeile in der Dokumentation folgen, was Sie Ihre Frage beantworten eingefügt werden:.

Parameter placeholders can only be used to insert column values. They can not be used for other parts of SQL, such as table names, statements, etc.

+0

Ich bin Einfügen eines *** Spaltenwert ***. Die Zeile in der Dokumentation bedeutet, dass der folgende Code ist illegal: 'c.execute ('select id% s wo username =% s' ('Benutzer', 'bob'))' – mercador

+1

@mercador Recht, der 'from% s' piece verursacht den Fehler, da Sie versuchen, den Tabellennamen zu parametrisieren. Der Vorteil der Verwendung von 'execute' auf diese Weise ist, dass es hilft, SQL-Injection zu verhindern, aber wenn Sie die richtigen Sicherheitsvorkehrungen nehmen (was ich auf kein Experte bin, aber richtige sanitization bedeuten würde/der Parameter zu entkommen), können Sie Verwenden Sie die in Python integrierte String-Formatierung, um die Abfrage zu erstellen, und übergeben Sie sie dann an "execute". Auch hier ist SQL-Injection das Hauptanliegen. Hoffe das hilft! – RocketDonkey

5

MySQLdb ermöglicht dicts als Abfrageparameter . This response zeigt alle verschiedenen Möglichkeiten, dies zu tun. Sie brauchen nur einen secuence als solche Parameter (Tupel, dict ...), um als zweiten Parameter auf „Ausführen“. Formatieren Sie Ihre Abfrage NICHT als einen einzigen Parameter für die Methode "execute" oder Sie werden SQL-Injection-Angriffen ausgesetzt sein. Siehe:

"SELECT * FROM users WHERE username = '%s'" % (user) 

denken, was passieren würde, wenn:

user = "peter;DROP TABLE users" :_(

Die andere Art und Weise befestigt ist, wie es die MySQLdb Bibliothek ermöglicht die notwendige Kontrolle zu handhaben.

Ich weiß nicht, was falsch ist, weil Ihre Frage gut für mich funktioniert:

# Connect to db 
# Open a cursor 
stmt = "SELECT * FROM users WHERE username = %(user)s" 
cursor.execute(stmt, {"user": "bob"}) 
user = cursor.fetchone() 
print user 

{'username': 'bob', 'alias': 'bobby', 'avatar': 'default', 'fullname': 'bob'} 

Können Sie uns weitere Informationen geben?