2012-10-11 49 views
6

que quieren transmitir los parámetros de consulta a cursor.execute() método de MySQLdb como un diccionario llamado, de manera que son escaparon de inyección SQL.Python MySQLdb: Los parámetros de consulta como un diccionario llamado

¿Puede explicar por qué esto da KeyError:

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

manual de MySQLdb http://mysql-python.sourceforge.net/MySQLdb.html dice:

* paramstyle

cadena constante que indica el tipo de marcador de parámetro formato esperado por la interfaz. Establecer en 'formato' = códigos de formato ANSI C printf, p. '... WHERE nombre =% s'. Si se utiliza un objeto de mapeo para conn.execute(), entonces la interfaz realmente usa 'pyformat' = códigos de formato extendido de Python, p. '... WHERE nombre =% (nombre) s'. Sin embargo, la API no permite actualmente la especificación de más de un estilo en paramstyle *

Respuesta

6

La línea en la siguiente documentación de lo que ha pegado puede responder a su pregunta:.

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

Estoy insertando un *** valor de columna ***. La línea en la documentación significa que el siguiente código es ilegal: 'c.execute ('seleccionar id de% s donde nombre de usuario =% s', ('usuarios', 'bob'))' – mercador

+1

@mercador Right, the 'from% s' pieza es lo que está causando el error ya que está tratando de parametrizar el nombre de la tabla. El beneficio de usar 'execute' de esta manera es que ayuda a prevenir la inyección de SQL, pero si toma las precauciones de seguridad adecuadas (que no soy un experto, pero implicaría una correcta desinfección/escape de los parámetros), puede use el formato de cadena de Python construido para construir la consulta y luego páselo a 'execute'. De nuevo, la inyección SQL es la principal preocupación. ¡Espero que esto ayude! – RocketDonkey

5

MySQLdb permite predice como parámetros de consulta . This response muestra todas las formas diferentes de hacerlo. Solo necesita proporcionar una secuencia como parámetro (tupla, dict ...) como segundo parámetro para "ejecutar". NO formatee su consulta como solo un parámetro para el método de "ejecución" o probablemente estará expuesto a ataques de inyección SQL. Ver:

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

pensar en lo que sucedería si:

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

La otra manera está asegurada, ya que permite a la biblioteca MySQLdb para manejar el control necesario.

No sé lo que está mal, debido a que su consulta funciona bien para mí:

# 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'} 

Puede darnos más información?

Cuestiones relacionadas