好吧,也许标题有点奇怪,但我会尝试解释它。
我正在使用SQLite数据库文件处理C#应用程序。我有一个DB类,其中所有与db通信的函数都是。
我的代码中有一个Insert
函数(注意,这不是由我做的):
public bool Insert(String tableName, Dictionary<String, String> data)
{
String columns = "";
String values = "";
Boolean returnCode = true;
foreach (KeyValuePair<String, String> val in data)
{
columns += String.Format(" {0},", val.Key.ToString());
values += String.Format(" '{0}',", val.Value);
}
columns = columns.Substring(0, columns.Length - 1);
values = values.Substring(0, values.Length - 1);
try
{
this.ExecuteNonQuery(String.Format("insert into {0}({1}) values({2});", tableName, columns, values));
}
catch (Exception fail)
{
MessageBox.Show(fail.Message);
returnCode = false;
}
return returnCode;
}
一切看起来都不错。但是我希望通过参数化查询来阻止某些SQLInjection
。但问题是,查询永远不会有相同的长度。那我该如何处理呢?
我的意思是:我希望这个单个函数用于包含3列的表,以及用于包含8列的表。全部动态。有没有人知道如何做到这一点(以一种很好/正确的方式)?
答案 0 :(得分:1)
我将插入函数重写为 InsertSecure 方法,
现在您可以使用参数插入所有值。
我在代码中添加了一些注释,以便更好地了解如何调整您的程序 然后,您可以通过这种方式将其称为:
public void HowToCall()
{
// I assume that "columnA" and "columnB" is set by you and it is safe,
// unsafe are values "valueA" and "valueB"
Dictionary<string, string> data = new Dictionary<string, string>()
{ { "columnA", "valueA" }, { "columnB", "valueB" } };
// then call new method
InsertSecure("table_name", data);
}
InsertSecure 内容:
public bool InsertSecure(String tableName, Dictionary<String, String> data)
{
// table name can not contains space
if (tableName.Contains(' ')) { return false; }
String columns = "";
String values = "";
Boolean returnCode = true;
foreach (KeyValuePair<String, String> val in data)
{
columns += String.Format(" '{0}',", val.Key.ToString());
// all values as parameters
values += String.Format(" @{0},", val.Key.ToString());
}
columns = columns.Substring(0, columns.Length - 1);
values = values.Substring(0, values.Length - 1);
try
{
// setup your connection here
// (connection is probably set in your original ExecuteNonQuery)
SQLiteConnection cnn = new SQLiteConnection();
cnn.Open();
SQLiteCommand cmd = cnn.CreateCommand();
cmd.CommandType = System.Data.CommandType.Text;
// prepare insert command based on data
cmd.CommandText = String.Format("insert into {0} ({1}) values ({2})",
tableName, columns, values);
// now your command looks like:
// insert into table_name (columnA, columnB) values (@columnA, @columnB)
// next we can set values for any numbers of columns
// over parameters to prevent SQL injection
foreach (KeyValuePair<String, String> val in data)
{
// safe way to add parameter
cmd.Parameters.Add(
new SQLiteParameter("@" + val.Key.ToString(), val.Value));
// you just added for @columnA parameter value valueA
// and so for @columnB in this foreach loop
}
// execute new insert with parameters
cmd.ExecuteNonQuery();
// close connection and set return code to true
cnn.Close();
returnCode = true;
}
catch (Exception fail)
{
MessageBox.Show(fail.Message);
returnCode = false;
}
return returnCode;
}
我可以通过此程序安全地插入数据。
注意:我没有测试它的项目,如果它被正确写入,
但是没有语法错误,逻辑看起来还不错。请尝试并享受。