2012-04-22 1 views
1

Мне интересно добавить sql-запросы parametrize в моем приложении ASP.net. Я видел несколько хороших статей об Avoid SQL Injection.Использовать параметризованные sql-запросы, когда SQLCommand используется в отдельном классе

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

Однако этот способ не является полезным для меня, поскольку я пара подключения к БД в отдельный класс, так как я использовать его.

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 без использования входов Textbox.

ответ

1

Это вполне разумно сделать, но попросите своего класса перезвонить (лямбда/делегат), чтобы получить параметры. Это статический метод в классе, который вызывается различными перегруженными методами экземпляра:

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

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 логика будучи в этом другом классе, в отличии от класса вызова нужно знать, как построить запрос и т.д.

It также делает ваш код более удобочитаемым, потому что вы видите AddUser или UpdateUser или ChangePassword как вызовы методов и не должны читать SQL в этот момент, чтобы попытаться угадать, что происходит в программе.

ОДНАКО, если вы собираетесь сделать что-то вроде этого, вы должны проверить некоторые MicroORMs, мой личный фаворит PetaPoco (или NuGet version)

PetaPoco и другие подобные Массивный и Dapper позволит вам сделать что-то вроде:

database.Insert(u); 

Где u - объект пользователя, который сопоставляется с таблицей вашего БД. Он использует ADO.NET и обязательно использует SQL-параметры.

0

Я бы предложил использовать LINQ to SQL, который automatically parametrizes everything.

Q. Как LINQ to SQL защищен от SQL-инъекций?

A. Внедрение SQL было значительным риском для традиционных SQL-запросов, сформированных путем объединения пользовательского ввода. LINQ to SQL избегает такой инъекции, используя SqlParameter в запросах. Пользовательский ввод преобразуется в значения параметров. Этот подход предотвращает использование вредоносных команд с пользовательского ввода.

Вы можете insert, update and delete из базы данных SQL в прямой манере, используя DataContext (щелкните правой кнопкой мыши на вашем проекте, чтобы добавить новый элемент и добавить LINQ to SQL Classes шаблон, а затем использовать Проводник сервера для добавления объектов к нему).

Я не работал с этим в то время, но я считаю, что ваш код будет выглядеть примерно так:

UserData user = new UserData(); 

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

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

При вызове SubmitChanges, LINQ к SQL автоматически генерирует и выполняет SQL команды, которые он должен будет передать ваши изменения обратно в базу данных.

Edit1:

В качестве дополнительного примечания, чтобы получить существующий элемент из базы данных, вы можете сделать это:

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

О, и как это мой стандартный полис при ответе вопросы о базах данных с регистрационной информацией, я должен умолять вас, ради любви к Богу и всему святому, до salt and hash your users' passwords.