我有两个问题 1.我有一个列名字符串,它是列名。我如何在SQL查询中使用它? 2.该方法是否容易出现SQL注入?用字符串列名查询SQL表名
这就是我现在所拥有的,
List<string> Columnnames = new List<string>();
cmd = new SqlCommand("Select "+Columnnames+" from test");
我有两个问题 1.我有一个列名字符串,它是列名。我如何在SQL查询中使用它? 2.该方法是否容易出现SQL注入?用字符串列名查询SQL表名
这就是我现在所拥有的,
List<string> Columnnames = new List<string>();
cmd = new SqlCommand("Select "+Columnnames+" from test");
回答您的问题:
问题1 - 你的代码更改为类似:
List<string> Columnnames = new List<string>();
// Code that populates Columnnames here
cmd = new SqlCommand("Select " + string.Join(",", Columnnames) + " from test");
问题2 - 取决于你如何填充Columnnames
。如果这是从网上输入填充,那么是的。
谢谢你的作品。列名填充在具有所有列名的列表框中的用户输入上。是否仍有机会进行SQL注入? – Mike 2014-09-03 10:52:03
@ user3272054这里的UI是什么?网站的? WinForm的? WPF?如果答案是“网络”,那么答案是“是的,绝对的,简单的”。如果答案是“winform”/“WPF”,那么“有点可能是的,但他们必须真的努力工作,而且直接去sql server会容易些,因为他们可能有访问权限” – 2014-09-03 10:57:54
@MarcGravell:谢谢。它是winforms。 – Mike 2014-09-03 10:59:18
可以的Columnnames
列表转换为逗号分隔的列值。就像这样:
string columns = Columnnames.Aggregate((x,y) => x + "," + y);
cmd = new SqlCommand("Select "+columns+" from test");
这种方法很容易受到SQL注入有人可以轻松地发送列名像column ;drop database yourDB
所以它是一个坏主意。
首先检查Columnames是否有任何值。 其次做一个函数来创建类似于dus columna,columnb
SqlCommend应该看起来像这样select columna,columb from test;
您应该将列名连接到查询,以便每个列名用下一个逗号分隔,例如, (伪)
define sql = "SELECT "
for columnName in columnNames:
concatenate sql,columnName
if columnName is not last:
concatenate sql,","
end if
end for
concatenate sql," FROM test"
漏洞取决于列名的来源。如果你有内部不变的列名列表,那么没有风险,但是如果它们来自外部源,比如使用应用程序的用户,那么它肯定会倾向于SQL注入。
如果列名来自外部源,那么是的,您必须将它们连接到字符串中。理想情况下,您应该使用[
/]
,但只允许使用空格等列名 - 它不会更改有关SQL注入的任何内容,而且:允许用户指定列名将是SQL注入风险,除非您先列出它们。所以也许:
if(Columnnames.Count == 0) throw new ArgumentException(
"You need to specify at least one column");
var sql = new StringBuilder("select ");
bool first = true;
foreach(var name in Columnnames) {
if(!IsKnownColumnName(name)) { // <=== very important test
throw new ArgumentException("Invalid column name: " + name);
}
sql.Append(first ? "[" : ",[").Append(name).Append("]");
first = false;
}
sql.Append(" from test");
...
cmd.CommandText = sql.ToString();
这确实有帮助!再次感谢!! – Mike 2014-09-03 10:59:55
列名从哪里来?用户输入?为什么你需要它是动态的? – 2014-09-03 10:42:28
真正防止SQL注入的唯一方法是将所有内容都视为在SQL本身中查看或存储过程,并具有非常好的触发器和验证。 – Franck 2014-09-03 10:44:53
是的,它是用户输入来自具有所有列名的列表框。 – Mike 2014-09-03 10:45:25