【问题标题】:Question about Stored procedures and sql commands in the code关于代码中存储过程和sql命令的问题
【发布时间】:2011-06-06 06:21:57
【问题描述】:

我是 sql 新手,我尝试使用内联 /in-code sql 命令对数据进行操作。但是,我知道您有时需要在 trans-sql 中编写很多代码。当我编写它时,人们会说它受到 sql 注入的影响。那我就不知道怎么办了……

考虑到我不是数据库编程方面的专家,对我来说做什么会更容易。我应该使用存储过程还是内联文本。以及如何将参数传递给存储过程? (例如,如果我有来自文本框的输入)。

【问题讨论】:

  • 购买一本关于 SQL 的书并阅读并练习示例可能需要一周或更短的时间 - 这可能非常值得。
  • 我就是这么做的。但我正在考虑在存储过程中做所有的事情。我不知道如何将参数传递给存储过程

标签: asp.net sql stored-procedures


【解决方案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-- 的内容,或者只是在用户名文本框中添加 ' 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); 
}

如果你想使用 Store Procedures,也一样:

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 的东西并担心这个,框架将为您处理所有已知操作。

最常用的数据库 ORM 之一是 NHibernateADO 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();                
}

而且您无需考虑,缓存注入并发等...

【讨论】:

  • ORM,太慢了。感谢你的回答。我想我会坚持使用存储过程,因为它们更整洁
  • 如果你知道如何使用它是相当快的:)
【解决方案2】:

存储过程不是编写 sql 注入安全代码的强制选项。您可以使用可以解决 sql 注入攻击的参数化查询。

【讨论】:

    【解决方案3】:

    您不必使用存储过程来避免“SQL 注入”;您只需要使用参数化查询(显然是存储过程)。

    The C# Station ADO.NET Tutorial

    Using Parameters with a SqlCommand and a Stored Procedure

    裸骨示例(尚未编译):

    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;
    }
    

    【讨论】:

    • 哦,好吧。我更喜欢使用存储过程。因为如果我有很多代码,就会有很多混乱。有没有地方或者书可以读到如何用vs2010构建和应用存储过程?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2011-03-03
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多