黑馬程序員—ADO.Net筆記(防止sql注入)

---------------------- Windows Phone 7手機開發.Net培訓、期待與您交流! ----------------------

 

通過ADO.Net在程序中執行SQL語句。

ADO.Net中提供了對各種不同數據庫的統一操作接口。

 

連接SQLServer

1.    連接字符串:程序通過連接字符串指定要連哪臺服務器上的、哪個實例的哪個數據庫、用什麼用戶名密碼等。

2.    項目內嵌mdf文件形式的連接字符串:

  Data Source=.\SQLEXPRESS; AttachDBFilename=|DataDirectory|\Database1.mdf;

Integrated Security=True; User Instance=True.

.\SQLEXPRESS”表示“本機上的SQLEXPRESS實例”,如果數據庫實例名不是SQLEXPRESS,則需要修改。

Database1.mdf”爲mdf的文件名。

3.       ADO.Net中通過SqlConnection類創建到SQLServer的連接。

4.       ADO.Net中的連接等資源都實現了IDisposable接口,可以使用using進行資源管理。

 

類:

SqlConnection代表一個數據庫連接;

SqlCommand表示向服務器提交的一個命令(SQL語句等);

SqlDataReader提供一種從 SQL Server 數據庫讀取行的只進流的方式。

1.       執行有多行結果集的用ExecuteReader

2.       SqlDataReader類的GetStringGetInt32等方法只接受整數參數,也就是序號。

        用GetOrdinal方法根據列名動態得到序號。

 

 

方法:

SqlCommand類的方法:

ExecuteNonQuery()執行SQL語句,返回受影響的行數。

ExecuteScalar()執行查詢,並返回結果集中第一行的第一列,返回值object類型.

ExecuteReader()執行查詢,返回多行多列,返回值是SqlDataReader類型。

 

ExecuteScalar()應用1:查表中數據條數,查數據最大值等。

                         應用2:得到自動增長字段的主鍵值。

A.    cmd CommandText = “select count(*) from T_Users”

              int i = Convert.ToInt32(cmd.ExecuteScalar());

B.    cmd.CommandText = “Insert into T_Users(UserName,Password)

       output inserted Id values(‘admin’,’666666’)”;

       int i = Convert.ToInt32(cmd.ExecuteScalar()); //得到自動增長字段的主鍵值

 

ExecuteReader()應用:

SqlDataReader reader = cmd.ExecuteReader();

while (reader.Read()) //每次讀一行,返回值爲true表示讀到了數據,否則無數據。

//讀取多行數據時,只能逐行向前處理,無法回頭,無法向前跳着走

{

              String username = reader.GetString(reader.GetOrdinal(“UserName”));

}

//GetOrdinal():在給定列名稱的情況下獲取序列號

 

 

1

向數據庫插入數據

using(SqlConnection conn =new SqlConnection(@“Data Source=.\SQLEXPRESS;

AttachDBFilename=|DataDirectory|\Database1.mdf;

Integrated Security=True; User Instance=True”))

//字符串前要加@,否則字符串裏面的’\’將被當成轉義字符。

{

        conn.Open();

        using(SqlCommand cmd = conn.CreateCommand())

        //向服務器提交的一個命令

       {

              cmd.CommandText = “Insert into MyTable(Name) values(‘aaa’)”; //創建插入命令

              cmd.ExecuteNonQuery(); //執行命令

       }

}

 

2

從數據庫中查詢數據

using(SqlConnection conn =new SqlConnection(@“Data Source=.\SQLEXPRESS;

AttachDBFilename=|DataDirectory|\Database1.mdf;

Integrated Security=True; User Instance=True”))

{

      conn.Open();

      using(SqlCommand cmd = conn.CreateCommand())

      {

             cmd.CommandText = “select * from T_Users”; //創建查詢命令

             using (SqlDataReader reader = cmd.ExecuteReader())  //執行查詢

             {

                    while (reader.Read()) //reader.Read()true表示讀到了數據,否則沒讀到數據。

                    {

                            //取得表中字段值

                           string username = reader.GetString(reader.GetOrdinal(“UserName”));

                           int id = reader.GetInt32(reader.GetOrdinal(“Id”));

                           string password = reader.GetString(reader.GetOrdinal(“Password”));

                          //下面做一些邏輯業務處理

                   }

            }

      }

}

 

3

簡單的登錄程序

Console.WriteLine(“請輸入用戶名:”);

string username = Console.ReadLine();

Console.WriteLine(“請輸入密碼:”);

string password = Console.ReadLine();                 //輸入1’ or ‘1’=’1造成SQL注入漏洞攻擊

 

using (SqlConnection conn =new SqlConnection(@“Data Source=.\SQLEXPRESS;

AttachDBFilename=|DataDirectory|\Database1.mdf;

Integrated Security=True; User Instance=True”))

{

   conn.Open();

   using (SqlCommand cmd = conn.CreateCommand())

   //向服務器提交的一個命令對象

  {

       cmd.CommandText = “select * from T_Users where UserName=’”+username+””;

//先到表中查用戶輸入的用戶名對應的信息

       using (SqlDataReader reader = cmd.ExecuteReader())  //執行查詢

       {

               if(reader.Read())

               {

                       //用戶名存在

                      string dbpassword = reader.GetString(reader.GetOrdinal(“Password”));

                      if(dbpassword == password)  //比較數據庫中保存的密碼與輸入的密碼是否一致

                      {

                             Console.WriteLine(“登錄成功!”);

                     }

                    else

                   {

                          Console.WriteLine(“密碼錯誤,登錄失敗!”);

                   }

            }

           else  //Read()返回false,就是沒有查找到這個用戶名

          {

                 //用戶名不存在

                Console.WriteLine(“用戶名錯誤!”);

          }

      }

  }

}

 

SQL注入與參數化查詢

簡單的登錄程序(另一種實現方法)

只部分修改:

using (SqlCommand cmd = conn.CreateCommand())

{

       cmd.CommandText = “select count(*) from T_Users where UserName=’”+username+””+

and Password=’’’+password+””;

       int i=Convert.ToInt32(cmd.ExecuteScalar()); //返回count(*)的值(即符合條件數據條數)

       if (i>0)

       {

              Console.WriteLine(“登錄成功!”);

}

else

{

       Console.WriteLine(“用戶名或密碼錯誤!”);

}

}

以上方法的CommandText是拼接字符串所成,會有sql注入漏洞。

例如用戶輸入用戶名爲admin,密碼爲“1’ or ‘1’= '1的字符串,

則上面的查詢語句就變爲:

select count(*) from T_Users where UserName=’admin’ and Password=’1’ or ‘1’= '1’;

後一個條件爲真,則整個條件爲真。故查找出來的是表中所有行數,則i>0,即登錄成功。

 

防止Sql注入,用參數化查詢cmd.Parameters.Add()

using (SqlCommand cmd = conn.CreateCommand())

{

       cmd.CommandText = “select count(*) from T_Users where UserName=@UserName and

Password=@Password”; //相當於佔位符

       cmd.Parameters.Add(new SqlParameter(“UserName”,username));

       cmd.Parameters.Add(new SqlParameter(“Password”,password));

       int i=Convert.ToInt32(cmd.ExecuteScalar()); //返回count(*)的值(即符合條件數據條數)

       if (i>0)

       {

              Console.WriteLine(“登錄成功!”);

      }

     else

    {

            Console.WriteLine(“用戶名或密碼錯誤!”);

    }

}

 

 

總結:程序中一般分五步:

       首先加入SqlConnection所在的命名空間:using System.Data.SqlClient;

1.       創建連接數據庫的對象

2.       打開數據庫

3.       創建命令對象

4.       執行命令

5.       獲取數據庫返回的結果,進行處理

 

防止Sql注入,儘量用參數化查詢

 

---------------------- Windows Phone 7手機開發.Net培訓、期待與您交流! ----------------------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章