[ASP.NET] 最好習慣用SqlParameter

  • 11201
  • 0
  • 2011-11-11

最好習慣用SqlParameter

iThome電腦報498期(2011..04.09)有著一則這樣的新聞Mass SQL Injection來襲,百萬網址受駭

SQL Injection這個名詞我想大慨不用多作解釋,而它不是個新名詞了,只是這麼多年來它始終存

在於我們的Web Application中,就像小強存在我們的生活中一樣

 

這則新聞中提到被駭的網站中,以ASP及ASP.NET網站數量最多,但真的用ASP及ASP.NET這麼

脆弱嗎?這倒也不是,而是寫code的我們該負起一些責任,常在論壇中看到以下類似的程式碼

 

 

select * from xx where code ='"+Request.QueryString["code"]+"'

 

 

這樣的程式碼,雖然不至於會錯,但它是卻為SQL Injection開啟大門,就像聲聲呼喚SQL Injection

來你家坐坐一樣,對於來自Request端的字串完全無過濾,原封不動的傳入,幸好在ASP.NET裡提供

了一個東西叫做SqlParameter,或許有些人會反駁那就寫個function過濾一下就好了啊,幹麻用

SqlParameter呢,用SqlParameter還要多寫一堆程式碼,其實SqlParameter除了幫我們過濾不合法

的字元之外,它也做到了型態的過濾,長度的過濾等等動作,能夠提供我們的程式在執行SQL Command

時能更安全,而且其實它寫起來一點都不麻煩,重點還在於習慣它就好了微笑

 

 

SqlParameter的用法大致如下 (一點都不麻煩)

using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
{
    conn.Open();
    using (SqlCommand command = new SqlCommand())
    {
        command.Connection = conn;
        command.CommandText = "select * from basecode where code =@code";
        command.Parameters.Add("@code", SqlDbType.VarChar, 4).Value = this.Code.Text;
        .....
        .....
    }
    conn.Close();
}

 

 

再來看前陣子遇到的另一個論壇例子(連結就不po了微笑),原發問者的問題大致是遇到在下SQL Command時

,因為時間條件的字串含有『上午,下午』這樣的文字,以致於會傳回例外的錯誤,而原發問者本身的

程式碼也是用串字串的方式,當然解法可以針對時間條件的字串去拆解再組合之類的方法來處理,不過

這也太麻煩了,如果使用SqlParameter來進行SQL Command的處理,這個問題應該早就不會發生了

,接著就以這個例子示範一下

 

 

在畫面上我拉了二個Button,一個是以SqlParameter方式進行SQL Command,而另一個則是以串

字串方式來進行SQL Command,另外拉了一個GridView以證明SQL Command有被正確的執行,

並且得到預期的結果

 

image

 

 

在.cs裡,直接以一個變數來模擬外界傳入的時間條件(當然是含有『上午,下午』這樣的文字)

string initdate = "2005/10/25 下午 07:06:18.000";

 

 

而採用SqlParameter的Button1_Click事件程式碼,如下

 try
    {
        using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
        {
            conn.Open();
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = conn;
                command.CommandText = "select * from basecode where initdate =@initdate";
                command.Parameters.Add("@initdate", SqlDbType.DateTime).Value = DateTime.Parse(initdate);
                IDataReader idr = command.ExecuteReader();
                this.GridView1.DataSource = idr;
                this.GridView1.DataBind();
                idr.Dispose();
            }
            conn.Close();
        }
    }
    catch (Exception ex)
    {
        this.TextBox1.Text = ex.ToString();
    }

 

執行結果,未發生Exception,且順利得到預期結果

image

 

 

串字串的Button2_Click事件程式碼,如下

    try
    {
        using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
        {
            conn.Open();
            using (SqlCommand command = new SqlCommand())
            {
                command.Connection = conn;
                command.CommandText = "select * from basecode where initdate ='" + initdate + "'";
                IDataReader idr = command.ExecuteReader();
                this.GridView1.DataSource = idr;
                this.GridView1.DataBind();
                idr.Dispose();
            }
            conn.Close();
        }
    }
    catch (Exception ex)
    {
        this.TextBox1.Text = ex.ToString();
    }

 

執行結果,發生Exception

image

 

 

結論,與其想盡辦法過濾特殊字串來避免SQL Injection,或是花盡心思來處理字串以確保SQL

Command可被正常執行,倒不如快點跟SqlParameter成為好朋友吧!眨眼睛

 

 

 

 

 

 

若本文對您有所幫助,歡迎轉貼,但請在加註【轉貼】及來源出處,並在附上本篇的超連結,感恩您的配合囉。

By No.18