我是sql的新手,我尝试使用内联/内嵌代码sql命令对数据进行操作。但是,我知道你需要在trans-sql中编写很多代码。当我写它时,人们说它受到sql注入。然后我不知道该怎么做......
考虑到我不是数据库编程方面的专家,我会更容易做些什么。我应该使用存储过程还是内联文本。我如何将参数传递给存储过程? (例如,如果我有来自文本框的输入)。
答案 0 :(得分:1)
我们举一个例子来登录用户:
正常查询类似于
SELECT name, lastLogin
FROM [tblUsers]
where username = 'balexandre' AND password = 'veryhard';
将此代码放入代码中时,它会很有用。
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--
或{{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);
}
现在,如果你工作并使用像数据库ORM(对象关系映射)这样的东西,你可以避免考虑所有这些,而不是纠正所有SQL的东西而担心这个,框架将为您处理所有已知的操作。
最常用的数据库ORM之一是NHibernate和ADO Entity Framework。
你可以使用LINQ查询,你的调用就像:
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);
}
如果你有一个商店程序,它是一样的(下面的例子只显示另一种方式来调用它)
public User GetUser(string username, string password)
{
return _db.Users.FirstOrDefault(x => x.User == username && x.Password == password);
}
您无需考虑,缓存,注入,并发等...
答案 1 :(得分:0)
您不必使用存储过程来避免'SQL注入;你只需要使用参数化查询(显然存储过程就是这样)。
The C# Station ADO.NET Tutorial
Using Parameters with a SqlCommand and a Stored Procedure
Bare bones示例(尚未编译):
string connectionString = "Server=(local);DataBase=Northwind;Integrated Security=SSPI";
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand("MyStoredProcName_CustOrderHist", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@CustomerID", custId));
// execute the command
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
// do something with results
}
conn.close;
}
答案 2 :(得分:0)
存储过程不是编写sql注入安全代码的强制选项。您可以使用可以解决SQL注入攻击的参数化查询。