如何使用SQL参数从SQL Server获取数据集

时间:2013-09-11 22:13:51

标签: c# sql sql-server sql-injection sqlparameters

我正在研究C#项目,我是这项技术的新手。

我想从SQL Server 2008中读取一些数据,并编写以下代码

public User select(string username, string password)
{
    string connection = ConfigurationManager.ConnectionStrings["lawyersDBConnectionString"].ConnectionString.ToString();
    string sql = string.Format("select * from users where userName = '{0}' and password = '{1}'", username, password);

    SqlConnection con = new SqlConnection();            
    con.ConnectionString = connection;

    DataSet ds = new DataSet();
    SqlDataAdapter da = new SqlDataAdapter(sql, con);            

    User user = new User();
    DataRow dr;

    try
    {
            da.Fill(ds);
            dr = ds.Tables[0].Rows[0];

            user.Id = Convert.ToInt16(dr["userID"]);                
            user.FirstName = (string)dr["firstName"];
            user.LastName = (string)dr["lastName"];
            user.Email = (string)dr["email"];
            user.Username = (string)dr["userName"];
            user.Password = (string)dr["password"];
            user.type = (string)dr["type"];

            return user;
    }
    catch (Exception ex)
    {                
            return null;
    }
}//end of select method

但我读过一篇关于SQL注入的文章,我想使用SQL参数来避免这种情况,但我不知道如何。

3 个答案:

答案 0 :(得分:9)

这是对代码的简单修改。未经测试,但基本上它包括在一次性对象周围添加using statement以及使用带有参数集合的SqlCommand

string connection = ConfigurationManager.ConnectionStrings ["lawyersDBConnectionString"].ConnectionString.ToString();
string sql = "select * from users where userName = @uname and password = @pwd";

 DataSet ds = new DataSet();
 using(SqlConnection con = new SqlConnection(connection))
 using(SqlCommand cmd = new SqlCommand(sql, con))
 {
    con.Open();
    cmd.Parameters.AddWithValue("@uname", username);
    cmd.Parameters.AddWithValue("@pwd", password);

    using(SqlDataAdapter da = new SqlDataAdapter(cmd))
    {
         User user = new User();
         DataRow dr;
         da.Fill(ds);
         dr = ds.Tables[0].Rows[0];

         user.Id = Convert.ToInt16(dr["userID"]);                
         user.FirstName = (string)dr["firstName"];
         user.LastName = (string)dr["lastName"];
         user.Email = (string)dr["email"];
         user.Username = (string)dr["userName"];
         user.Password = (string)dr["password"];
         user.type = (string)dr["type"];
         return user;
    }
}

注意命令文本不直接包含用户和密码的字符串,而是一个简单的参数占位符(@uname and @pwd)。将参数添加到SqlCommand集合时,这些占位符称为参数名称。

查看检索到的数据的用法我强烈建议您查看可以直接翻译User对象中所有代码的简单ORM工具,如Dapper

答案 1 :(得分:1)

有趣的是,String.Format的工作方式与SQL参数没有太大区别。唯一真正的区别是你指定了每个参数的数据类型,它允许SQLCommand正确地清理(读取:阻止sql注入)用户的输入。

以下是如何更改代码以使用SQL参数的示例。

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    using (SqlCommand command = new SqlCommand("select * from users where userName = @pUsername and password = @pPassword", connection))
    {
        command.Parameters.Add(new SqlParameter("pUsername", username));
        command.Parameters.Add(new SqlParameter("pPassword", password));

        DataSet ds = new DataSet();
        SqlDataAdapter da = new SqlDataAdapter(command);  

        // The rest of your code here...
     }
}

我想指出的一些事情:

  1. 用户名通常不区分大小写,因此查询应该使用LIKE或UCASE()比较来查找用户名。
  2. 从查询中可以明显看出,您的密码未经过哈希处理或加密。这真是太糟了。阅读散列密码。 https://crackstation.net/hashing-security.htm
  3. 基本上你在这里创建的东西叫做对象关系管理器。除非你特别感兴趣学习如何开发一个我强烈建议你使用经过试验和测试的。我个人使用nHibernate。 Hibernate是作为Java的ORM编写的,nHibernate非常适合.Net应用程序。实体框架是微软的ORM。我不认为它与nHibernate相当,但它不断改进。

答案 2 :(得分:0)

这是我为此编写的可重用方法:

n^m = m^n  implies
m*log(n) = n*log(m)