在列名上使用C#SQL参数化

时间:2013-03-14 21:07:32

标签: asp.net sql sqldatasource

我遇到了问题。我希望这可以工作,但它没有:

SqlDataSource.SelectCommand = "SELECT blah1, blah2 FROM myTable WHERE @ColumnName = @Value";

SqlDataSource.SelectParameters.Add("ColumnName", System.Data.DbType.String, "one");
SqlDataSource.SelectParameters.Add("Value", System.Data.DbType.String, "two");

它不会取代第一个参数“ColumnName”。如果我删除该参数并将列名放在其中,它将起作用:

SqlDataSource.SelectCommand = "SELECT blah1, blah2 FROM myTable WHERE one = @Value";

SqlDataSource.SelectParameters.Add("Value", System.Data.DbType.String, "two");

我有一个UI,用户可以在其中选择要搜索的数据库列名称。我想保护自己免受任何类型的注射攻击。我有什么想法可以让它发挥作用吗?

我读到的一个想法是使用查找表从DropDownList获取索引并以这种方式拉取列名。我可以做到这一点,但如果可能的话,我宁愿让参数化工作,因为这对我来说似乎更自然。

提前感谢您提供的任何帮助。

3 个答案:

答案 0 :(得分:1)

我担心你不能那样做,你可以做的只是一个小技巧:

SELECT blah1, blah1 FROM myTable 
WHERE (@blah1 is null or blah1 = @blah1)
   or (@blah2 is null or blah2 = @blah2)

并提供所有参数@ blah1,@ blah2但仅指定您需要的参数。

Mike Christensen为您提供的NB解决方案基本上构建了具有正确条件的字符串,在最简单的情况下将是

public bool BuildQueryWithCondition(string fieldName, string fieldValue) {
   var queryTemplate = "SELECT blah1, blah1 FROM myTable WHERE {0} = @Value"
     , query = string.Format(queryTemplate, fieldName)
   SqlDataSource.SelectCommand = query;
   SqlDataSource.SelectParameters.Add("Value", System.Data.DbType.String, fieldValue);
}

答案 1 :(得分:1)

由于在解析SQL并生成执行计划之后解析了查询参数,因此实际上无法使用参数动态构建SQL。我建议以安全的方式构建SQL字符串本身。也许首先创建enum个有效列名:

enum DbColumns { One, Two, Three };

然后像这样构建SQL字符串:

DbColumns colName = (DbColumns)Enum.Parse(typeof(DbColumns), "One");
SqlDataSource.SelectCommand = String.Format("SELECT blah1, blah1 FROM myTable WHERE {0} = @Value", colName);

另一个想法是使用正则表达式验证列名,可能只允许[a-z]

答案 2 :(得分:0)

我找到了一种方法来包含参数化列名的解决方法。我有同样的问题,但想出了一个不同的方式,因为我是唯一使用列名的人,所以我相信这仍然是一个安全的赌注。

            String sqlcomm = "SELECT * FROM Asset WHERE " + assetColName + " = ";
            command.CommandText = sqlcomm + "$assetColValue";

            //command.CommandText = @"SELECT * FROM Asset WHERE $assetColName = '$assetColValue'";
            //command.Parameters.AddWithValue("$assetColName", assetColName);

            command.Parameters.AddWithValue("$assetColValue", assetColValue);

从上面的代码中可以看出。我几乎尝试了你所做的事情,然后我不得不评论出来。然后我将字符串连接在一起,并能够使用我的参数化列名和值,然后安全地添加值。然而,列名不是安全的,但这是一种只有我将使用的方法,所以它仍然有点安全。如果您想要更安全但可以了解修复,则可以添加正则表达式。