2012-07-18 19 views

Respuesta

17

Utilizo SQLAlchemy para consultas directas todo el tiempo.

Ventaja principal: le brinda la mejor protección contra los ataques de inyección SQL. SQLAlchemy hace lo correcto, independientemente de los parámetros que le arrojes.

Me parece que funciona de maravilla para ajustar el SQL generado en función de las condiciones también. ¿Mostrando un conjunto de resultados con múltiples controles de filtro encima? Simplemente crea tu consulta en un conjunto de construcciones if/elif/else y sabrás que tu SQL seguirá siendo oro.

Aquí es un extracto de un cierto código en vivo (versión anterior SA, por lo que la sintaxis puede variar un poco):

# Pull start and end dates from form 
# ... 
# Build a constraint if `start` and/or `end` have been set. 
created = None 
if start and end: 
    created = sa.sql.between(msg.c.create_time_stamp, 
     start.replace(hour=0, minute=0, second=0), 
     end.replace(hour=23, minute=59, second=59)) 
elif start: 
    created = (msg.c.create_time_stamp >= 
       start.replace(hour=0, minute=0, second=0)) 
elif end: 
    created = (msg.c.create_time_stamp <= 
       end.replace(hour=23, minute=59, second=59)) 

# More complex `from_` object built here, elided for example 
# [...] 
# Final query build 
query = sa.select([unit.c.eli_uid], from_obj=[from_]) 
query = query.column(count(msg.c.id).label('sent')) 
query = query.where(current_store) 
if created: 
    query = query.where(created) 

El código de dónde viene es mucho más compleja, pero quería poner de relieve la código de rango de fecha aquí. Si tuviera que construir el SQL utilizando el formato de cadenas, probablemente habría introducido un agujero de inyección SQL en alguna parte, ya que es mucho más fácil olvidarse de citar valores.

1

Después de trabajar en un pequeño proyecto mío, decidí intentar usar MySQLDB, sin SQL Alchemy.

Funciona bien y es bastante fácil de usar, he aquí un ejemplo (creé una pequeña clase que se encarga de todo el trabajo de la base de datos)

import MySQLdb 
from MySQLdb.cursors import DictCursor 

class DatabaseBridge(): 
    def __init__(self, *args, **kwargs): 
     kwargs['cursorclass'] = DictCursor 
     self.cnx = MySQLdb.connect (**kwargs) 
     self.cnx.autocommit(True) 
     self.cursor = self.cnx.cursor() 

    def query_all(self, query, *args): 
     self.cursor.execute(query, *args) 
     return self.cursor.fetchall() 

    def find_unique(self, query, *args): 
     rows = self.query_all(query, *args); 
     if len(rows) == 1: 
      return rows[0] 

     return None 

    def execute(self, query, params): 
     self.cursor.execute(query, params) 
     return self.cursor.rowcount 

    def get_last_id(self): 
     return self.cnx.insert_id() 

    def close(self): 
     self.cursor.close() 
     self.cnx.close() 

database = DatabaseBridge(**{ 
     'user': 'user', 
     'passwd': 'password', 
     'db': 'my_db' 
    }) 

rows = database.query_all("SELECT id, name, email FROM users WHERE is_active = %s AND project = %s", (1, "My First Project")) 

(Es un ejemplo tonto).

Funciona como un encanto PERO usted tiene que tomar esto en consideración:

  • multihilo no es compatible! Está bien si no trabajas con multiprocessing desde Python.
  • No tendrá todas las ventajas de SQLAlchemy (Contenedor de base de datos a clase (modelo), Generación de consultas (select, where, order_by, etc.)). Este es el punto clave sobre cómo desea trabajar con su base de datos.

Pero, por otra parte, y al igual que SQLAlchemy, hay protecciones agains't ataques de inyección SQL:

una consulta básica sería así:

cursor.execute("SELECT * FROM users WHERE data = %s" % "Some value") # THIS IS DANGEROUS 

pero debe hacerlo :

cursor.execute("SELECT * FROM users WHERE data = %s", "Some value") # This is secure! 

¿Has visto la diferencia? Lea de nuevo;)

La diferencia es que reemplacé %, por ,: Pasamos los argumentos como ... argumentos a la ejecución, y estos se escapan. Al usar %, los argumentos no se escapan, lo que permite ataques de inyección de SQL.

La última palabra aquí es que depende de su uso y de lo que planea hacer con su proyecto. Para mí, SQLAlchemy estaba en exceso (¡es un script de shell básico!), Así que MysqlDB era perfecto.

Cuestiones relacionadas