如果没有查询生成器或 ORM,如何避免 SQL 注入漏洞?
How do you avoid an SQL injection vulnerability without a query builder or an ORM?
假设我有一个如下所示的函数(忽略此处的任何语法错误,除非它们与问题相关,我是 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}");`)
}
没有什么可以阻止用户将他们自己的 SQL 注入博客 post 文本字段。只要语法正确,他们就不能执行他们想要的任何命令吗?我想知道您是否应该做一些额外的事情来防止这种情况发生,或者最好的做法是只使用 ORM 而不是构建自己的 SQL 语句。
非常感谢。
使用parameters防止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]));
};
备注:
除了 return await ...
什么都不做的 async function
是 anti-pattern。在这种情况下删除 async
/await
,函数将完全相同。
运行 直接在数据库对象上查询非常容易;尝试将其抽象为一个单独的 execute()
函数实际上是在让您的生活变得更加艰难。那是因为数据库对象比 运行ning 查询提供了更多的东西,并且在长 运行 中您将需要更多的包装函数,这是不必要的复杂性。我创建了openDb()
,直接returns一个数据库对象就够了
我为此使用了 open()
with caching,以防止不必要地向同一数据库发送多个连接。这样可以多次调用OpenDb
,现有连接为re-used.
对于 inserting/updating rows,您应该使用 .run()
而不是 .exec()
。
通常:Return API 来自您自己函数的承诺。在这里,open()
给你一个承诺,openDb()
returns 它,createBlogPost()
接受它,然后 returns 它给调用者。这样 createBlogPost()
可以在调用代码中被 await
编辑,并且错误处理也能正常工作:
async function test_createBlogPost() {
try {
const result = await createBlogPost(1, 'Hello World');
console.log(result);
} catch (err) {
console.log("createBlogPost failed", err);
}
}
假设我有一个如下所示的函数(忽略此处的任何语法错误,除非它们与问题相关,我是 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}");`)
}
没有什么可以阻止用户将他们自己的 SQL 注入博客 post 文本字段。只要语法正确,他们就不能执行他们想要的任何命令吗?我想知道您是否应该做一些额外的事情来防止这种情况发生,或者最好的做法是只使用 ORM 而不是构建自己的 SQL 语句。
非常感谢。
使用parameters防止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]));
};
备注:
除了
return await ...
什么都不做的async function
是 anti-pattern。在这种情况下删除async
/await
,函数将完全相同。运行 直接在数据库对象上查询非常容易;尝试将其抽象为一个单独的
execute()
函数实际上是在让您的生活变得更加艰难。那是因为数据库对象比 运行ning 查询提供了更多的东西,并且在长 运行 中您将需要更多的包装函数,这是不必要的复杂性。我创建了openDb()
,直接returns一个数据库对象就够了我为此使用了
open()
with caching,以防止不必要地向同一数据库发送多个连接。这样可以多次调用OpenDb
,现有连接为re-used.对于 inserting/updating rows,您应该使用
.run()
而不是.exec()
。通常:Return API 来自您自己函数的承诺。在这里,
open()
给你一个承诺,openDb()
returns 它,createBlogPost()
接受它,然后 returns 它给调用者。这样createBlogPost()
可以在调用代码中被await
编辑,并且错误处理也能正常工作:async function test_createBlogPost() { try { const result = await createBlogPost(1, 'Hello World'); console.log(result); } catch (err) { console.log("createBlogPost failed", err); } }