9

我的想法是通过 C# (3.5) Winforms 应用程序通过 MySQL .NET 连接器 6.2.2 与 MySQL 数据库对话,为插入/更新/选择创建一些通用类。

例如:

public void Insert(string strSQL)
{
   if (this.OpenConnection() == true)
   {
       MySqlCommand cmd = new MySqlCommand(strSQL, connection);
       cmd.ExecuteNonQuery();
       this.CloseConnection();
   }
}

然后从程序中的任何地方,我都可以通过传递一个 SQL 查询字符串来运行一个有/没有用户输入的查询。

阅读 SO 开始让我知道这可能会导致 SQL 注入攻击(对于任何用户输入值)。是否有清理输入的 strSQL 或者我需要在每个需要执行数据库功能的方法中创建单独的参数化查询?

更新1:

我的最终解决方案如下所示:

public void Insert(string strSQL,string[,] parameterValue)
{
   if (this.OpenConnection() == true)
   {
       MySqlCommand cmd = new MySqlCommand(strSQL, connection);

       for(int i =0;i< (parameterValue.Length / 2);i++)
       {                        
       cmd.Parameters.AddWithValue(parameterValue[i,0],parameterValue[i,1]);          
       }

       cmd.ExecuteNonQuery();
       this.CloseConnection();
   }}
4

8 回答 8

12

参数化很容易做到。比清理 SQL 查询要容易得多,而且比手动转义更不容易弄乱或出错。

从这个教程页面稍微编辑了复制/粘贴,因为我觉得很懒:

// User input here
Console.WriteLine("Enter a continent e.g. 'North America', 'Europe': ");
string userInput = Console.ReadLine();

string sql = "SELECT Name, HeadOfState FROM Country WHERE Continent=@Continent";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@Continent", userInput);

using (MySqlDataReader dr = cmd.ExecuteReader())
{
    // etc.
}

那不是那么难,是吗?:)

于 2010-05-05T18:24:02.213 回答
11

您绝对应该使用参数化查询来保证自己的安全。

不过,您不必每次都手动创建参数化查询。您可以修改您提供的通用方法以接受以下集合MySqlParameters

public void Insert(string strSQL, List<MySqlParameter> params)
{
    if(this.OpenConnection() == true)
    {
        MySqlCommand cmd = new MySqlCommand(strSQL, connection)
        foreach(MySqlParameter param in params)
            cmd.Parameters.Add(param);

        cmd.ExecuteNonQuery();
        this.CloseConnection();
    }
}

我还应该提到,在使用完连接后,您应该非常小心地清理连接(通常在一个using块中处理,但我在您的代码示例中看不到那种详细程度)。

于 2010-05-05T18:20:35.410 回答
1

事后检测到 SQL 注入是不可能的(换句话说,一旦你构建了一个动态查询字符串,就不可能区分什么是“真正的”SQL 与任何注入的 SQL)。

如果您的意图是允许用户执行任意 SQL,那么您似乎不会太担心 SQL 注入(因为这是 SQL 注入的目的)。

于 2010-05-05T18:16:59.963 回答
1

我预计很难清理将用于 SQL 的原始文本。如果可能的话,我会尝试使用参数化操作。

一个例外是,如果您没有公开该函数,并且您从未传入由原始用户输入构造的字符串。

于 2010-05-05T18:17:02.330 回答
1

如果您使用MySqlParameter并且不生成纯字符串查询,那么您是安全的。

于 2010-05-05T18:17:09.607 回答
1

你不能真正做到这一点 - 你需要编写一个 SQL 解析器,至少可以说它不平凡且容易出错。

咬紧牙关,对您的查询进行参数化。

于 2010-05-05T18:17:39.710 回答
1

我建议使用 IDataParameter 对象来参数化您的查询。

于 2010-05-05T18:18:43.110 回答
1

是的,您需要创建参数化查询,其他任何事情都会引入 SQL 注入的风险

于 2010-05-05T18:25:32.070 回答