为什么String.Format工作但SqlCommand.Parameters.Add没有?

时间:2015-10-15 15:50:47

标签: c# sql-server

我有一个Project表,其中包含两列 - ProjectIdProjectName - 我正在编写一个函数来构造并执行SqlCommand来查询数据库具有给定名称的项目的ID。此命令有效,但容易受到SQL Injection

的攻击
string sqlCommand = String.Format("SELECT {0} FROM {1} WHERE {2} = {3}",
            attributeParam, tableParam, idParam, surroundWithSingleQuotes(idValue));

SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
    DataTable attributes = new DataTable();
    adapter.Fill(attributes);
    ...
}

attributeParamtableParamidParamidValue都是字符串。例如,它们可能分别是"ProjectId""Project""ProjectName""MyFirstProject"surroundWithSingleQuotes围绕一个包含''的字符串,因此surroundWithSingleQuotes(idValue) == "'MyFirstProject'"。我试图尽可能地编写这个函数,因为我可能希望将来从表中获取所有给定的属性。

虽然上面的String.Format有效,但这不是:

string sqlCommand = String.Format("SELECT @attributeparam FROM {0} WHERE " + 
    "@idparam = @idvalue", tableParam);

command.Parameters.Add(new SqlParameter("@attributeparam", attributeParam));
command.Parameters.Add(new SqlParameter("@idparam", idParam));
command.Parameters.Add(new SqlParameter("@idvalue", 
     surroundWithSingleQuotes(idValue)));

SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
    DataTable attributes = new DataTable();
    adapter.Fill(attributes);
    ...
}

我不确定为什么。我没有收到任何错误消息,但是当我使用DataTable填充SqlDataAdapter时,DataTable不包含任何内容。以下是我采取的各种方法,但无济于事:

  • 关注this answerMicrosoft's documentation,使用AddWithValue或使用Parameters.AddSqlParameter.Value
  • 使用实际值或参数字符串有选择地替换{0}中的{1}{2}{3}String.Format

在我的代码的其他地方,我使用参数化查询(虽然只有一个参数)没问题。

2 个答案:

答案 0 :(得分:7)

SQL中的参数基本上只适用于 - 而不是列或表的标识符。在您的示例中,只有最终参数表示值。

如果您需要在列名和表名方面保持动态,那么您需要自己构建SQL的那一部分。 非常小心,因为与SQL注入攻击相关的所有正常原因。理想情况下,只允许表和列值的已知白名单。如果您需要更一般,我建议执行非常严格的验证,quote the identifiers以避免与关键字发生冲突(或完全禁止这些冲突)。

当然,继续使用SQL参数作为值。

答案 1 :(得分:0)

这是一个有效的声明: SELECT * FROM SomeTable WHERE SomeColumn=@param

虽然这不是: SELECT * FROM @param

这意味着您可以使用值的参数,而不是表名,视图名,列名等。