Supongamos que tengo una función similar a la siguiente (ignore cualquier error de sintaxis aquí a menos que sea relevante para la pregunta, soy nuevo en SQL):
// This function updates the database using the command passed as a parameter const execute = async (command) => { open({ filename: "test.db", driver: sqlite3.Database, }).then((db) => { db.exec(command); }); }; // Takes the user ID and their input and adds it to the database const createBlogPost = async (userId, text) => { await execute(`INSERT INTO posts (user_id, post) VALUES ("${userId}", "${text}");`) }No hay nada que impida que el usuario inyecte su propio SQL en el campo de texto de la publicación del blog. ¿No podrían ejecutar cualquier comando que deseen siempre que la sintaxis sea correcta? Me pregunto si hay algo adicional que se supone que debe hacer para evitar esto, o si es una mejor práctica usar un ORM en lugar de crear sus propias declaraciones SQL.
Muchas gracias.
Utilice parámetros para evitar la inyección de SQL.
function openDb() { return open({ filename: "test.db", driver: sqlite3.cached.Database, }); }; const createBlogPost = (userId, text) => { return openDb().then(db => db.run("INSERT INTO posts (user_id, post) VALUES (?, ?);", [userId, text])); };Notas:
Una async function que no hace nada más que return await ... es un antipatrón. Elimine el async / await en tal caso, la función funcionará exactamente igual.
Ejecutar una consulta es muy fácil directamente en un objeto de base de datos; en realidad estás haciendo tu vida más difícil al tratar de abstraerla en una función de execute() separada. Esto se debe a que el objeto de la base de datos ofrece algunas cosas más que ejecutar consultas, y necesitaría cada vez más funciones de contenedor a largo plazo, lo que es una complejidad innecesaria. openDb() , que simplemente devuelve directamente un objeto de base de datos, eso es suficiente.
He usado open() con almacenamiento en caché para esto, para evitar enviar spam innecesariamente a varias conexiones a la misma base de datos. De esta manera, puede llamar a OpenDb varias veces y la conexión existente se reutiliza.
Se supone que debes usar .run() en lugar de .exec() para insertar/actualizar filas .
En general: devuelva las promesas de la API desde sus propias funciones. Aquí, open() le da una promesa, openDb() la devuelve, createBlogPost() la toma y luego también la devuelve a la persona que llama. De esta manera, se puede await a createBlogPost() en el código de llamada, y el manejo de errores también funciona como debería:
async function test_createBlogPost() { try { const result = await createBlogPost(1, 'Hello World'); console.log(result); } catch (err) { console.log("createBlogPost failed", err); } }