我是 node 的新手,对使用 sqlstring 的动态参数化查询有疑问。
以下代码的问题在于,过滤器是可选的,具体取决于用户传递给函数的内容,因此它们的顺序可以更改(因此很难分别传递每个过滤器参数)。据我所知,Sqlstring 使用顺序来确定哪些参数与正确的问号匹配。
所以我只剩下一次将所有过滤器传递给 Sqlstring,但是如果没有过滤器处于事件状态,那么我只剩下一个用于过滤器变量的空字符串,这将引发 sql 语法错误。
let filter = idList !== '' ? ` AND id IN(${idList})` : '';
filter += locationsList !== '' ? ` AND a.locationID IN(${locationsList})` : '';
filter += start !== undefined ? ` AND a.lastEdited >= ${start}` : '';
filter += end !== undefined ? ` AND a.lastEdited <= ${end}` : '';
filter += name !== undefined ? ` AND a.name LIKE '%${name}%'` : '';
const qry = `
SELECT
a.id 'id'
,a.number 'number'
,a.name 'name'
,a.locationID 'locationID'
,a.location 'location'
,a.lastEdited 'lastEdited'
,a.userID 'owner'
FROM tbl_foo_${'?'} a
WHERE a.id > ${'?'} ${'?'} LIMIT ${'?'};`;
let values = [ id, cursor, filter, limit ];
const rows = query(db, qry, values);
//inside of the query function it does this and then runs the query against the database
if (qry.includes('?')) {
sanitizedQry = sqlstring.format(qry, values);
}
它产生的查询看起来像这样:
SELECT
a.id 'id'
,a.number 'number'
,a.name 'name'
,a.locationID 'locationID'
,a.location 'location'
,a.lastEdited 'lastEdited'
,a.userID 'owner'
FROM tbl_foo_36 a
WHERE a.id > 1 '' LIMIT 100;
有更好的方法吗?
最佳答案
如果你看一下 sqlstring npm page ,关于 SqlString.format
是这样说的:
This looks similar to prepared statements in MySQL, however it really just uses the same SqlString.escape() method internally.
如果适本地使用 SqlString.escape
,您会变得更好。
但问题是,您没有在需要的地方防止 SQL 注入(inject)。例如,在这个声明中你应该有注入(inject)保护,但你没有。下面是它应该是什么样子的示例:
filter += name !== undefined ? ` AND a.name LIKE '%${SqlString.escape(name)}%'` : '';
name
大概是用户输入变量,此时您需要防止 SQL 注入(inject)。所有用户输入变量都需要直接应用 SQL 注入(inject)保护。
在您已经使用变量构建 SQL 片段之后,您绝对不能提供 SQL 注入(inject)保护。当您构建您的 filter
SQL 片段然后尝试稍后插入它时,您在做什么……这实际上是您在进行有意的 SQL 注入(inject)。
免责声明:使用准备好的语句(或等效技术),您将获得比这种转义式保护更高级别的保护。转义式保护是针对 SQL 注入(inject)攻击的最低级别的保护,您可以使用它并且仍然有任何保护。
免责声明 2: 允许用户输入部分表名也可能非常危险,并且很难正确转义。
例如,假设您有一堆表,tbl_foo_1
到 tbl_foo_99
。并且您希望您的用户可以访问所有这些。但是,如果后来有人添加了一个 tbl_foo_secret
会怎样?你猜怎么了?您的用户也可以访问它,因为您让他们选择自己的表名。或者,如果您添加整个架构 tbl_foo_top_secret
会怎么样?他们可以很容易地告诉您表后缀是 tbl_foo_top_secret.table_name
,并且您的代码会很好地接受它,因为在这个库中不会转义句点。因此,您可能希望添加自己的自定义检查以确保表名后缀是可接受的。
关于javascript - 参数化动态查询/SQL 清理 NodeJS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57382704/