这个问题仅出于教育目的,因为我目前尚未构建任何使用用户输入构建SQL查询的应用程序。
就是说,我知道在ADO.NET中您可以通过执行以下操作来防止SQL注入:
OleDbCommand command = new OleDbCommand("SELECT * FROM Table WHERE Account = @2", connection); command.Parameters.AddWithValue("@2", "ABC");
但是,假设您的应用程序的设计方式使得用户可以实际输入表的名称,那么您可以执行以下操作吗?(我不在乎允许用户提供表名是否是一个坏主意,我只想知道是否可以执行以下操作……)
OleDbCommand command = new OleDbCommand("SELECT * FROM @1 WHERE Account = @2", connection); command.Parameters.AddWithValue("@1", "Table"); command.Parameters.AddWithValue("@2", "ABC");
当我运行第二个代码时,我不断收到异常消息,说SQL查询不完整,我想知道问题是我尝试做的事情根本无法完成还是忽略了某些事情。
不可以,查询参数可以代替SQL语句中的 一个标量值 。 例如,单个字符串文字,日期文字或数字文字。
它不必在WHERE子句中。在SQL中可以有表达式的任何地方,都可以包含标量值,因此也可以包含参数。例如,在联接条件中,选择列表中或ORDER BY或GROUP BY子句中。
您 不能 将查询参数用于:
如果需要使查询的这些部分中的任何部分都可由用户定义,则需要通过将应用程序变量内插或连接到字符串中来构建SQL查询字符串。这使得很难防御SQL注入。
在这种情况下,最好的防御方法是将可以安全插值到SQL字符串中的特定值 列入白名单 ,例如,在代码中定义的一组表名。让用户从这些预先批准的值中选择一个表,但是不要在随后执行的SQL代码中逐字使用输入。
用户输入可以提供值,但绝不能提供代码。
您可能会发现我的演示文稿“ SQL注入神话和谬论”有帮助。我在该演示文稿中涵盖了白名单(我的示例使用PHP,但该想法适用于任何编程语言)。