一尘不染

参数化查询与SQL注入

c#

我是Asp.net的新手,我刚刚开始使用课程。最近,我创建了一个类,该类将为我处理大多数SQL查询,从而不必在所有文件上重复创建新连接。

我创建的方法之一将SQL查询作为参数并返回结果。我知道我应该使用参数化查询来避免SQL注入。我的问题是,当我将查询作为字符串参数传递时,该怎么办?

例如,这是我要调用的方法:

public static DataTable SqlDataTable(string sql)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
    {
        SqlCommand cmd = new SqlCommand(sql, conn);
        cmd.Connection.Open();
        DataTable TempTable = new DataTable();
        TempTable.Load(cmd.ExecuteReader());
        return TempTable;
    }
}

因此,从另一个文件中,我想使用这种方法:

DataTable dt = new DataTable();

dt = SqlComm.SqlDataTable("SELECT * FROM Users WHERE UserName='" + login.Text  + "' and Password='" + password.Text + "'");

if (dt.Rows.Count > 0)
{
   // do something if the query returns rows
}

这行得通,但仍然容易受到注射的侵害吧?有没有办法将变量作为参数传递给字符串?我知道如果我为查询创建一个新的SQLCommand对象并使用Parameters.AddWithValue,则可以执行此操作,但是我希望所有SQL命令都位于单独的类中。


阅读 304

收藏
2020-05-19

共1个答案

一尘不染

这行得通,但仍然容易受到注射的侵害吧?

是的,您的代码非常容易受到SQL注入的攻击。

我知道我应该使用参数化查询来避免SQL注入。

哦,是的。

我的问题是,当我将查询作为字符串参数传递时,该怎么办?

您根本不应该将查询作为字符串参数传递。相反,您应该将查询作为包含占位符和这些占位符值的字符串参数传递:

public static DataTable SqlDataTable(string sql, IDictionary<string, object> values)
{
    using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
    using (SqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = sql;
        foreach (KeyValuePair<string, object> item in values)
        {
            cmd.Parameters.AddWithValue("@" + item.Key, item.Value);
        }

        DataTable table = new DataTable();
        using (var reader = cmd.ExecuteReader())
        {
            table.Load(reader);
            return table;
        }
    }
}

然后像这样使用您的函数:

DataTable dt = SqlComm.SqlDataTable(
    "SELECT * FROM Users WHERE UserName = @UserName AND Password = @Password",
    new Dictionary<string, object>
    {
        { "UserName", login.Text },
        { "Password", password.Text },
    }
);

if (dt.Rows.Count > 0)
{
   // do something if the query returns rows
}
2020-05-19