我用一些数据库查询构建了一个原型系统。因为它只是一个原型而且我对数据库很新,所以我只使用了直接字符串。这是我使用的字符串,它工作正常:
command = New OleDbCommand("SELECT * FROM " + prefix + "CanonicForms WHERE Type=1 AND Canonic_Form='" + item + "'", dictionary_connection)
现在,把它放在一个真实的系统中,我想使用更安全的参数化方法,所以在谷歌搜索后我想出了这个:
command = New OleDbCommand("SELECT * FROM @prefix WHERE Type=1 AND Canonic_Form=@form", dictionary_connection)
command.Parameters.AddWithValue("@prefix", prefix + "CanonicForms")
command.Parameters.AddWithValue("@form", item)
但是我得到的是一个不完整的查询子句的错误。我在两者之间做了哪些不同的事情?
答案 0 :(得分:3)
您的表名不能是参数。您可能必须进行某种形式的连接。它不是真正意义上的参数。
答案 1 :(得分:1)
如ek_ny所述,您的表名不能是参数。
如果您对注射非常偏执,那么在建立SQL字符串之前,请根据允许值的白名单检查传入的表名。
答案 2 :(得分:1)
@cost,我同意它会很好,但它不是一个存在的功能。通常,它假定您的WHERE
子句是查询的动态部分,其他所有内容(包括SELECT
列表和表名称)都是静态的。事实上,大多数WHERE
子句甚至不是动态的,只有搜索值本身。您也不能以这种方式动态添加列名。这肯定可以构建,但它需要查询引擎更多地了解数据库引擎,这是一种微软不喜欢打开的蠕虫病毒。
想象一下一个下拉菜单,其中包含一些桌面名称,例如'Jobs','People','Employers',这是一些天真的开发人员所建立的。在回发时,该值用于SELECT * FROM
。一个简单的SQL注入就是跳转到该菜单中未列出的另一个表所需的全部内容。传递一些非常奇怪的东西很容易就会抛出一个可以揭示数据库内容的错误。纯值参数化查询仍然可以被破坏,但表面积要小得多。
有多个表前缀的人使用模式,这是一个选项吗?