Давайте рассмотрим пример для входа в систему пользователя:
нормальный запрос будет выглядеть примерно так:
SELECT name, lastLogin
FROM [tblUsers]
where username = 'balexandre' AND password = 'veryhard';
, если поместить это в код, это будет kind'a
using (SqlConnection connection = new SqlConnection(connectionString)) {
DataSet userDataset = new DataSet();
string query = "SELECT name, lastLogin FROM [tblUsers] where username = '" + txtUser.Text.Trim() + "' AND password = '" + txtPassword.Text.Trim() + "'";
SqlDataAdapter myCommand = new SqlDataAdapter(query, connection);
myCommand.Fill(userDataset);
}
Но это не помешает SQL-инъекции, попробуйте представить, что произойдет, если я добавлю в текстовое поле имени пользователя что-то вроде %
и в текстовом поле пароля что-то вроде ' OR 1=1--
или просто ' OR 1=1--
в имени пользователятекстовое окно.Это будет действительно так: 1
на самом деле равен 1
, и я буду зарегестрирован ...
пройденный запрос будет выглядеть так:
SELECT name, lastLogin
FROM [tblUsers]
where username = '' OR 1=1 --' AND password = '';
Вы понимаете, верно?
Но если мы будем использовать параметры в нашем запросе , этого никогда не произойдет, например:
using (SqlConnection connection = new SqlConnection(connectionString)) {
DataSet userDataset = new DataSet();
string query = "SELECT name, lastLogin FROM [tblUsers] where username = @username AND password = @password";
SqlDataAdapter myCommand = new SqlDataAdapter(query, connection);
myCommand.SelectCommand.Parameters.Add("@username", SqlDbType.VarChar, 30);
myCommand.SelectCommand.Parameters["@username"].Value = txtUser.Text.Trim();
myCommand.SelectCommand.Parameters.Add("@password", SqlDbType.VarChar, 30);
myCommand.SelectCommand.Parameters["@password"].Value = txtPassword.Text.Trim();
myCommand.Fill(userDataset);
}
То же самое, если вы хотите использовать Процедуры хранения :
using (SqlConnection connection = new SqlConnection(connectionString)) {
DataSet userDataset = new DataSet();
string query = "spGetUser";
SqlDataAdapter myCommand = new SqlDataAdapter(query, connection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
myCommand.SelectCommand.Parameters.Add("@username", SqlDbType.VarChar, 30);
myCommand.SelectCommand.Parameters["@username"].Value = txtUser.Text.Trim();
myCommand.SelectCommand.Parameters.Add("@password", SqlDbType.VarChar, 30);
myCommand.SelectCommand.Parameters["@password"].Value = txtPassword.Text.Trim();
myCommand.Fill(userDataset);
}
В наши дни , вы можете избежать всего этого, если вы работаете и используете что-то вроде базы данных ORM (объектно-реляционное отображение) что вместо исправления всех проблем SQL и беспокойства по этому поводу Framework позаботится обо всех известных вам действиях.
Одна из наиболее часто используемых баз данных ORM - NHibernate и ADO Entity Framework .
Вы можете использовать запросы LINQ с этим, и ваш вызов будет выглядеть так:
public User GetUser(string username, string password)
{
return _db.Users.FirstOrDefault(x => x.User == username && x.Password == password);
}
и если у вас была процедура хранения, она такая же (пример ниже просто показывает другой способ ее вызова)
public User GetUser(string username, string password)
{
return (from u in _db.spGetUser(username, password)
select u).FirstOrDefault();
}
И вы ненадо подумать, кэширование , инъекция , параллелизм и т. д. *