2012-04-22 83 views
1

我很有兴趣在我的ASP.net应用程序中添加参数化sql查询。我见过一些关于避免SQL注入的好文章。SQLCommand在单独的类中使用时使用参数化sql查询

string sql = string.Format("INSERT INTO [UserData] (Username, Password, Role, Membership, DateOfReg) VALUES (@Username, @Password, @Role, @Membership, @DateOfReg)"); 
     SqlCommand cmd = new SqlCommand(sql, conn); 
     try 
     { 
     cmd.Parameters.AddWithValue("Username", usernameTB.Text); 
     cmd.Parameters.AddWithValue("Password", passwordTB.Text); 
     cmd.Parameters.AddWithValue("Role", roleTB.Text); 
     cmd.Parameters.AddWithValue("Membership", membershipTB.Text); 
     cmd.Parameters.AddWithValue("DateOfReg", dorTB.Text); 

     conn.Open(); 
     cmd.ExecuteNonQuery(); 
     conn.Close(); 

find the Reference

但是这种方式对我来说并不实用,因为我对夫妇的DB连接到单独的类,因为我有重用。

public class DBconnection{  
    public int insertQuery(String query) { 



      int affectedRowCount = 0; 
      SqlConnection conn = null; 
      try{ 

       conn = new SqlConnection("Server=localhost;Database=master;UID=sa;PWD=sa;"); 
       SqlCommand cmd = new SqlCommand(query, conn); 
       cmd.CommandType = CommandType.Text; 

       conn.Open(); 
       affectedRowCount = cmd.ExecuteNonQuery(); 
       conn.Close();   

      } catch (Exception e){ 

         String error = e.Message; 

      } 

      return affectedRowCount; 
    } 
} 

因此,我只使用波纹管代码部分来调用上面的类并将值插入到数据库中。

String SQLQuery1 = insert into Article values('" + Txtname.Text + "','" + TxtNo.Text + "','" + Txtdescription.Text + "' ,0)"); 
DBconnection dbConn = new DBconnection(); 
     SqlDataReader Dr = dbConn.insertQuery(SQLQuery1); 

请帮我使用Parameterize sqlString来避免我Sql Injection。 要使用@name,@ No和@description而不使用文本框输入。

回答

1

这样做是完全合理的,但要让你的类回调(lambda/delegate)来获取参数。这是一类的静态方法,它是通过各种重载实例方法叫做:

private static int SqlExec(string ConnectionString, string StoredProcName, Action<SqlCommand> AddParameters, Action<SqlCommand> PostExec) 
     { 
      int ret; 
      using (var cn = new SqlConnection(ConnectionString)) 
      using (var cmd = new SqlCommand(StoredProcName, cn)) 
      { 
       cn.Open(); 
       cmd.CommandType = CommandType.StoredProcedure; 

       if (AddParameters != null) 
       { 
        AddParameters(cmd); 
       } 

       ret = cmd.ExecuteNonQuery(); 

       if (PostExec != null) 
       { 
        PostExec(cmd); 
       } 
      } 
      return ret; 
     } 

然后,使用示例:

public void Save() 
    { 
     Data.Connect().Exec("Project_Update", Cm => 
     { 
      Cm.Parameters.AddWithValue("@ProjectID", ID); 
      Cm.Parameters.AddWithValue("@PrimaryApplicantID", PrimaryApplicant.IdOrDBNull()); 
      Cm.Parameters.AddWithValue("@SecondaryApplicantID", SecondaryApplicant.IdOrDBNull()); 
      Cm.Parameters.AddWithValue("@ProjectName", ProjectName.ToDBValue()); 
     }); 
    } 

也有可能与非存储过程调用来做到这一点。

在你的情况下,它看起来像:

DBconnection.InsertQuery(
    "INSERT INTO [UserData] 
     (Username, Password, Role, Membership, DateOfReg) 
     VALUES (@Username, @Password, @Role, @Membership, @DateOfReg)" 
    ,cmd => { 
       cmd.Parameters.AddWithValue("Username", usernameTB.Text); 
       cmd.Parameters.AddWithValue("Password", passwordTB.Text); 
       cmd.Parameters.AddWithValue("Role", roleTB.Text); 
       cmd.Parameters.AddWithValue("Membership", membershipTB.Text); 
       cmd.Parameters.AddWithValue("DateOfReg", dorTB.Text); 
      } 
); 

这使你的所有数据库的东西在一起,你想要的方式,并让DBConnection的保持它的内部隔离。

+0

谢谢。这是为我工作,这是我寻找。 :) – devan 2012-04-23 05:04:38

1

如何编写特定的InsertQuery方法而不是通用的InsertQuery()方法?

例如:

public void AddNewUser(User u) 
{ 
    var query = "insert Users (name, password) values (@0, @1)"; 
    SqlCommand cmd = new SqlCommand(query, conn); 
     try 
     { 
     cmd.Parameters.AddWithValue("@0", u.UserName); 
     cmd.Parameters.AddWithValue("@1", u.Password); 
     } 
} 

这在这个其他类所有SQL逻辑之中,而不是调用类需要知道如何构造查询等

它的优点也使得您的代码更具可读性,因为您将AddUserUpdateUserChangePassword视为方法调用,并且无需在此刻读取SQL来尝试猜测程序中发生了什么。

无论其如果你打算做这样的事情,你应该检查出一些MicroORMs,我个人最喜欢的是PetaPoco(或NuGet version

PetaPoco和其他类似的大规模和小巧玲珑将让你做像这样:

database.Insert(u); 

其中u是一个用户对象,映射到您的数据库的表。它使用ADO.NET并确保使用SQL参数。

0

我会建议使用LINQ to SQL,其中automatically parametrizes everything

问:LINQ to SQL如何防止SQL注入攻击?

答:SQL注入一直是通过连接用户输入形成的传统SQL查询的重大风险。 LINQ to SQL通过在查询中使用SqlParameter避免了这种注入。用户输入变为参数值。这种方法可防止从客户输入中使用恶意命令。

您可以insert, update and delete从使用DataContext(在你的项目中单击鼠标右键添加一个新项目,并添加LINQ to SQL Classes模板,然后使用服务器资源管理器将对象添加到它)以直接的方式SQL数据库。

我还没有在一段时间这个工作,但我相信你的代码看起来有点像这样:

UserData user = new UserData(); 

user.Username = ...; 
user.Password = ...; 
user.Role = ...; 
user.Membership = ...; 
user.DateOfReg = ...; 

db.UserDatas.InsertOnSubmit(user); 
db.SubmitChanges(); 

当你调用的SubmitChanges,LINQ to SQL的自动生成和执行SQL命令,它必须将更改传回数据库。

EDIT1:

作为一个额外的音符,从数据库中检索现有的项目,你可以这样做:

var user = (from i in db.UserDatas 
      where i.UserName == "devan" 
      select i).Single(); 

哦,因为是我的标准政策,回答时关于数据库与登录信息的问题,我必须恳求你,为神的爱和所有的神圣,salt and hash your users' passwords