Sql 是否应在已准备好的查询中准备非变量列名?

Sql 是否应在已准备好的查询中准备非变量列名?,sql,prepared-statement,sql-injection,Sql,Prepared Statement,Sql Injection,在npm上使用准备好的语句和mysql包的示例如下所示: var sql = "SELECT * FROM ?? WHERE ?? = ?"; var inserts = ['users', 'id', userId]; sql = mysql.format(sql, inserts); 此处的“用户”和“id”是硬编码的。userId是由用户提供的变量。鉴于“用户”和“id”不是由用户提供的,那么在查询准备中包含这些信息有什么意义吗?这样做会不会不太安全 var sql = "SELECT

在npm上使用准备好的语句和mysql包的示例如下所示:

var sql = "SELECT * FROM ?? WHERE ?? = ?";
var inserts = ['users', 'id', userId];
sql = mysql.format(sql, inserts);
此处的“用户”和“id”是硬编码的。userId是由用户提供的变量。鉴于“用户”和“id”不是由用户提供的,那么在查询准备中包含这些信息有什么意义吗?这样做会不会不太安全

var sql = "SELECT * FROM users WHERE id = ?";
var inserts = [userId];
sql = mysql.format(sql, inserts);

SQL参数仅用于值,因此不能用于列或表名。在幕后,当准备语句时,RDBMS需要完全理解稍后将执行的查询。更改列或表名会更改查询的含义,因此不支持此操作


总之,您提到了列名和表名并不是来自用户输入,所以不管怎样,这消除了SQL注入的风险。如果它们来自程序外部,则解决方案是以编程方式验证它们(例如根据预定义的值列表)。

您应该明确列出所有列和表名,包括用所需的列替换
select*
。两个示例中都明确列出了列名。问题是,为什么文档编制人员要麻烦地将列名作为字符串传递给preparation函数。这似乎表明可能存在与直接在语句中写入列名相关的漏洞,但不清楚为什么会出现这种情况。至于select*,这不是问题的重点,只是举个例子。我的直觉是,由于列名不是来自用户输入,因此消除了SQL注入的风险。包文档中提供的示例在准备过程中包含了非变量列名,似乎表明如果按照我的第二个代码块编写,则可能存在漏洞。我会接受这个答案,即用户未提供的非变量列名不会通过SQL注入进行修改,除非将来有人反对。