1.SQL註入:SQL註入攻擊是web應用程式的一種安全漏洞,可以將不安全的數據提交給運用程式,使應用程式在伺服器上執行不安全的sql命令。使用該攻擊可以輕鬆的登錄運用程式。 例如:該管理員賬號密碼為xiexun,該sql的正確語句應該為: 如果在沒有做任何處理的情況下,在登錄名文本框中輸入(xux ...
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連接資料庫是面向連接的。讀表時,只能向前讀取,讀完數據後友用戶決定是否斷開連接。