2014-10-11 65 views
0

我是ASP.NET和C#的新手。从我正在阅读的一本书中,我编写了一条从数据库获取值的SELECT语句。但是,当我在网上搜索时,程序员说这是不安全的,不应该这样做。对于C#中的新手来说,我怎么知道我编程的方式是错误还是正确?有规则吗?例如,编写此代码的正确方法是什么:这条SELECT语句有什么不安全感?

using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CustomerDataConnectionString"].ConnectionString)) 
{ 
    SqlCommand cmd = new SqlCommand("SELECT CONVERT(varchar, CAST(plan_rate AS money), 1) FROM [dbo].[plans] WHERE plan_name = '" + Dropdownbox1.Text + "'", conn); 
    conn.Open(); 

    using (conn) 
    { 
     Object result = cmd.ExecuteScalar(); 
     if (result != null) 
      Label6.Text = "Plan rate: $" + result.ToString(); 
     else 
      Label6.Text = "Plan is not available in this state."; 

     conn.Close(); 
    } 

    ....... rest of code 

回答

5

这是正确的代码是不安全的。考虑如果Dropdownbox1.Text包含像'; DROP TABLE dbo.plans --这样的恶意内容会发生什么情况。由此产生的查询将是

SELECT CONVERT(varchar, CAST(plan_rate AS money), 1) 
FROM [dbo].[plans] 
WHERE plan_name = ''; 

DROP TABLE dbo.plans --' 

和您的plans表将被删除!

为了防止这种情况,而不是使用字符串连接一个参数化查询

SqlCommand cmd = new SqlCommand("SELECT CONVERT(varchar, CAST(plan_rate AS money), 1) FROM [dbo].[plans] WHERE plan_name = @plan_name", conn); 
cmd.Parameters.AddWithValue("@plan_name", Dropdownbox1.Text); 

当您使用参数,SQL查询引擎将参数的值作为数据而不是作为一个可能的指令。在security.stackexchange.com上阅读great answer以了解其差异。

在不相关的说明中,没有必要为conn提供两条using语句;一个就足够了:

using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CustomerDataConnectionString"].ConnectionString)) 
{ 
    conn.Open(); 

    SqlCommand cmd = new SqlCommand("SELECT CONVERT(varchar, CAST(plan_rate AS money), 1) FROM [dbo].[plans] WHERE plan_name = @plan_name", conn); 
    cmd.Parameters.AddWithValue("@plan_name", Dropdownbox1.Text); 
    Object result = cmd.ExecuteScalar(); 

    if (result != null) 
     Label6.Text = "Plan rate: $" + result.ToString(); 
    else 
     Label6.Text = "Plan is not available in this state."; 
} 
+0

请告诉OP _why_它是不安全的。 – 2014-10-11 17:35:54

+0

谢谢先生,如何使用参数保护Select语句?我可以做同样的事情,如果我错了,请纠正我的错误,现在我可以做的是:'DROP TABLE dbo_plans - '将存储在@plan_name中,并将传递给查询。我很抱歉如果这个问题是错误的,真的很感谢你的学习。 – user3345212 2014-10-11 17:47:49

+1

@ user3345212 - 参数不会简单地置于查询中。查询解析器实际上知道它们,并使用整个字符串作为一个不可分割的字符串。你实际上得到了你期望的行为 - 它搜索了一行,其中'plan_name'等于''; DROP TABLE dbo.plans --'。整个东西。它可能会减少0行,但这也如预期的那样。 – 2014-10-11 17:52:08