Ado.net 三[SQL注入,DataAdapter,sqlParameter,DataSet]


1.SQL注入:SQL注入攻擊是web應用程序的一種安全漏洞,可以將不安全的數據提交給運用程序,使應用程序在服務器上執行不安全的sql命令。使用該攻擊可以輕松的登錄運用程序。

   例如:該管理員賬號密碼為xiexun,該sql的正確語句應該為:

select * from Users where userName='xiexun'

   如果在沒有做任何處理的情況下,在登錄名文本框中輸入(xuxian' delete users--),單擊"登錄"按鈕之后,相當於傳了兩句sql語句,一句執行查詢之后,另外一句執行delete users之后整個表就沒數據了,這樣網站相當的不安全。

select * from Users where userName='xiexun'  delete users--sql語句的注釋,相當於把后面注釋了

 

 解決辦法:

 ①.通過@傳參的方式[存儲過程也是通過@傳參],sqlParameter方法

eg:

 public string Getswhere() 
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("select ID,username,PWD,loginname,qq,classname from Users  where 1=1");
            //獲取到它的用戶名
            string username = TxtUserName.Text.Trim();
            if (!string.IsNullOrEmpty(username))
            {
                //sb.Append(string.Format("and username='{0}'", username));
                //防SQL注入,通過@傳參的方式
                sb.Append(string.Format("and username=@username"));
                //怎么把值傳進去,通過sqlParameter數組
                //SqlParameter[] para = new SqlParameter[]
                //{
                //    //創建一個SqlParameter對象(第一個傳名稱,第二個傳值)
                //    new SqlParameter("@username",username)
                //};
                // para[0]表示數組對象的第一個里面添加
                //para[0] = new SqlParameter("@username",username);
para.Add(new SqlParameter("@username", username));
}
if(ddlsclass.SelectedIndex>0) { //sb.Append(string.Format("and ClassName='{0}'", ddlsclass.SelectedValue)); sb.Append(string.Format("and ClassName=@ClassName")); //para[1] = new SqlParameter("@ClassName",ddlsclass.SelectedValue);
 para.Add(new SqlParameter("@ClassName", ddlsclass.SelectedValue)); }
return sb.ToString(); }

         List<SqlParameter> para = new List<SqlParameter>();

        //我們把它放在list<>里,就有add方法

         private void openDB()
         {
          con = new SqlConnection(conStr);
          con.Open();//和數據庫建立起了連接
          //我們單獨把這兩句話封裝起來直接調用就好
         }
        //頁面一運行就執行這里面的內容
        protected void Page_Load(object sender, EventArgs e)
        {
          BindUser();
        }

       public void BindUser()
        {
            try
            {
                openDB();
                //得到sql語句
                //string sql = "select loginid,name,loginpwd,address,ClassName,mail from Users";
                string sql = Getswhere();
                //執行sql語句
                using (cmd = new SqlCommand(sql, con))
                //對象有了,我們要通過對象去執行sql語句
                {
                    //調用它,通過遍歷加到cmd里面去,我們把下面的值給cmd
                    //如果它里面有內容,我們就對它做一個循環
                    if (para.Count() > 0)
                    { 
                        foreach(var p in para)
                        {
                            cmd.Parameters.Add(p);
                        }
                    }
                    using (dr = cmd.ExecuteReader())
                    {
                        IdGridView.DataSource = dr;
                        IdGridView.DataBind();
                    }
                }
            }
            catch 
            {
                Response.Write("網站正在維護中.......!");
            }
        }

 這里,我們簡單用一個圖描述一下它的運行原理:前面的是沒有通過@傳參直接通過cmd與數據庫交互的結果,不安全;后面一種是加了"Parameter"

      

   我們現在是把這個值new SqlParameter("@username",username)給sqlParameter數組,sqlparameter給cmd,cmd再執行,這樣就可以避免SQL注入。

 

2.DataAdapter數據適配器

  ①.工作原理:DataAdapter數據適配器相當於中間環節[中間人]

       

     ⅰ.前端頁面委托數據適配器去實現和數據庫的交互;

     ⅱ.數據庫交互之后,再通過數據庫適配器再把數據放內存里;

     ⅲ.然后我們的網頁直接對內存里的東西讀和寫。(讀的話可以直接讀,寫的話要再通過適配器把它加進去),這樣數據庫處於非正常連接的情況下也可以操作數據。

    而之前的寫法:

      1.前端頁面要和數據庫交互,首先要建立起連接(數據庫連接);

      2.用完之后要釋放資源

     

  最大的好處就是:沒有必要每一個頁面都要與數據庫進行連接,降低了數據庫的壓力。

  

  ②用數據適配器做一個查詢[在程序中加存儲過程]     

<div>
          <asp:GridView ID="IdGridView" runat="server" AutoGenerateColumns="False">
            <Columns>
                <asp:BoundField DataField="id" HeaderText="ID" />
                <asp:BoundField DataField="username" HeaderText="用戶名" />
                <asp:BoundField DataField="PWD" HeaderText="密碼" />
                <asp:BoundField DataField="loginname" HeaderText="姓名" />
                <asp:BoundField DataField="qq" HeaderText="QQ" />
                <asp:BoundField DataField="classname" HeaderText="班級" />
                <asp:TemplateField HeaderText="詳情">
                    <ItemTemplate>
                        <a href="UserInfo.aspx?id=<%#Eval("ID") %>" target="_blank">詳情</a>
                        <%--<a href='UserInfo.aspx?userid=<%#Eval("UserId") %>' target="_blank">詳情</a
                       <%-- <a href="one.aspx?">詳情</a>--%>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
    </div>
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;

namespace _20160520
{
    public partial class egDataAp : System.Web.UI.Page
    {
        private string conStr = ConfigurationManager.ConnectionStrings["mySchool"].ToString();
        SqlConnection con = null;//相當於是電話
        SqlCommand cmd = null;//執行sql語句
        SqlDataReader dr = null;//用於儲存查詢結果
        //首先創建一個DataSet
        DataSet ds = new DataSet();
        protected void Page_Load(object sender, EventArgs e)
        {
            //用數據適配器的方式做一個查詢
             con = new SqlConnection(conStr);
            string ssql = "select ID,username,PWD,loginname,qq,classname from Users";
            using(cmd = new SqlCommand(ssql, con))
            {
                //創建一個DataAdapter,傳一個cmd
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                //應用數據適配器進行填充,填充到ds里
                da.Fill(ds);
                //指定一下數據源,.Tables[0]添加第一個table表
                //IdGridView.DataSource = ds;
                IdGridView.DataSource=ds.Tables[0];
                IdGridView.DataBind();
            }
        }
    }
}

 

  ③.DataAdapter調用存儲過程[在數據庫中加入存儲過程調用]

 private string conStr = ConfigurationManager.ConnectionStrings["mySchool"].ToString();
        SqlConnection con = null;//相當於是電話
        SqlCommand cmd = null;//執行sql語句
        SqlDataReader dr = null;//用於儲存查詢結果
        //首先創建一個DataSet
        DataSet ds = new DataSet();
        protected void Page_Load(object sender, EventArgs e)
        {
            //用數據適配器的方式做一個查詢
            con = new SqlConnection(conStr);
            //string ssql = "select ID,username,PWD,loginname,qq,classname from Users";
            //以上是之前的寫法,這里我們直接傳一個存儲過程名
            using (cmd = new SqlCommand("procegDataAp", con))
            {
                //指定一個sqlcommand的CommandType(默認情況下等於CommandType.text)為CommandType的存儲過程名
                cmd.CommandType = CommandType.StoredProcedure;
                List<SqlParameter> para = new List<SqlParameter>() 
                {
                    //通過sqlParameter數組把它加到cmd里面去,需指定名稱,類型,值
                    //模糊查詢
                    new SqlParameter("@UserName","%"+TxtsUserName.Text.Trim()+"%")
                };
                foreach(var a in para)
                {
                    cmd.Parameters.Add(a);
                }
                //創建一個DataAdapter,傳一個cmd
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                //應用數據適配器進行填充,填充到ds里
                da.Fill(ds);
                //指定一下數據源,.Tables[0]添加第一個table表
                //IdGridView.DataSource = ds;
                IdGridView.DataSource = ds.Tables[0];
                IdGridView.DataBind();
            }
        }

 

3.DataSet,DataTable,DataReader,DataAdapter的區別:

   ⅰ.DtaSet是用來做sql連接的一種方法,意思是把數據庫的副本存在應用程序里,相當於存在內存中的數據庫,應用程序開始運行時,把數據庫相關數據保存到DataSet.

   ⅱ.DataTable表示內存中數據的一個表,常和DefaultView使用獲取可能包括篩選視圖或游標位置的表的自定義視圖。

   ⅲ.DataReader對象是用來讀取數據庫最簡單的方式,它只能讀取不能寫入,而且是從頭至尾往下讀,無法只讀某條數據,但它占用內存小,速度快.

   ⅳ.DataAdapter對象是用來讀取數據庫,可讀取寫入數據,某條數據操作強,但它占用內存比DataReader大,速度慢,一般和DataSet連用

   注.DataSet表示一個數據集,是數據在內存中的緩存。可以包含多個表DataTable,DataSet連接數據時是非面向連接的,把表全部讀到sql中的緩存池,並斷開於數據庫的連接,DataReader連接數據庫是面向連接的。讀表時,只能向前讀取,讀完數據后友用戶決定是否斷開連接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM