前言: 從這篇部落格開始我們在介紹一下web開發的原則2,再上一章部落格中我們主要說了一些基本的Web開發原則,這篇我們在上篇的基礎上面在深入的講解一下。
- 用戶端驗證不能代替服務端驗證
(1) <asp:Button>來講,onclick是服務端事件,onclientClick是最終產生到用戶端瀏覽器中的onclick事件。
(2) 設定取款金額不能超過100元
1) 用戶端:<form id="form1" runat="server" onsubmit="if(parseInt(document.getElementById('TextBox1').value,10)>100){alert('最多隻能取款100元');return false;}">
2) 伺服器端:Label1.Text = "取款成功,金額是:" + TextBox1.Text;
(3) 如果禁用JavaScript(Internet選項—>安全—>自訂層級—>指令碼—>動態指令碼處理—>禁用,那麼用戶端JavaScript校正就被禁用了,就可以取款多於100元了)。
(4) 在服務端也要進行資料校正。
(5) 用戶端檢驗是為了很好地用戶端體驗,服務端校正是最後一次把關,防止惡意請求,後面要講的ASP.NET Validation就是ASP.NET內建的資料校正技術,會在用戶端和伺服器端同時校正。
註:建立一個Web頁面,拖放一個TextBox控制項,Button控制項和Label控制項,Button控制項的代碼為:
<asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="var value=document.getElementById('TextBox1').value; if(parseInt(value,10)>100){alert('金額不能大於100'); return false;}" onclick="Button1_Click" />
在Button控制項的事件下面寫入如下代碼:
1 protected void Button1_Click(object sender, EventArgs e) 2 3 { 4 5 if (Convert.ToInt32(TextBox1.Text) > 100) 6 7 { 8 9 Label1.Text = "禁止取款金額大於100元";10 11 }12 13 else14 15 {16 17 Label1.Text = "取款成功,金額是" + TextBox1.Text;18 19 }20 21 }
- 不要把敏感性資料,演算法寫在瀏覽器端
(1) 先舉一個簡單的例子來說明一下:
1 <script src="../script/jquery-1.4.1.min.js" type="text/javascript"></script> 2 3 <script type="text/jscript"> 4 5 $("#btnLogin").click(function () { 6 7 if ($("#UserName").val() == "admin" && $("#Password").val() == "citsoft") { 8 9 alert("登入成功");10 11 }12 13 else {14 15 alert("登入失敗");16 17 }18 19 });20 21 </script>
(2) 使用者在瀏覽器中查看原始碼就可以看到使用者名稱,密碼是什麼,在動態網站空間還是很少的那個年代,很多人的首頁都是用這種方法來實現的。
- 不要把機密資訊隱藏在HTML中
(1) 應該在服務端控制密碼不對則Visible=False,服務端控制項的HyperLink1.Visible=false是根本不輸出到用戶端的,在和Jquery等結合的時候無法用$(“#控制項ID”).Show()來顯示visible=false的控制項,因為控制項根本沒有渲染到Html中。
(2) 應該是在機密頁面開啟之前做許可權校正,而不是在一個頁面中做校正,如果正確就導向機密頁面,不正確就不導向。
(3) 只有密碼輸入正確了才顯示,實現代碼如下:
註:建立一個下載頁面.aspx,匯入純JavaScript代碼:
1 <body> 2 3 <form id="form1" runat="server"> 4 5 <div> 6 7 <input type="text" id="Password" /> 8 9 <input type="button" value="確定" onclick="var passwordID=document.getElementById('Password').value; if(Password=='111'){document.getElementById('div1').style.display='';}" />10 11 <div id="div1" style="display:none"><a href="http://www.cnblogs.com/hanyinglong.zip">點擊下載</a></div>12 13 <br />14 15 <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>16 17 <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />18 19 <br />20 21 <asp:HyperLink ID="HyperLink1" runat="server"22 23 NavigateUrl="http://www.cnblogs.com/hanyinglong.zip" Visible="False"></asp:HyperLink>24 25 </div>26 27 </form>28 29 </body>
在Button控制項的事件下面寫入如下代碼:
1 protected void Button1_Click(object sender, EventArgs e) 2 3 { 4 5 if (TextBox1.Text == "111") 6 7 { 8 9 HyperLink1.Visible = true;10 11 }12 13 }
- XSS漏洞
(1) 不要輕信使用者提交上來的資料。
(2) alert訊息太難看,因此開發一個ashx頁面用來統一展示訊息ShowMessage.ashx。
1 context.Response.ContentType = "text/html"; 2 3 context.Response.Write("<center><font color='red'>" + context.Request["msg"] + "</font></center>");4 5 context.Response.Write("<a href='javascript:history.back();'>返回上一頁</a>");
(3) 系統內部需要彈出訊息的時候只要將使用者的Redirect到ShowMessage.ashx?Msg=’訊息’,就可以,比如:
Response.Redirect("ShowMessage.ashx?Msg=使用者名稱不可為空");
(4) 建立一個發文章的檔案夾,在檔案夾上面加上view.aspx和ass.aspx頁面,首先
1)add.aspx中拖放一個TextBox和Button控制項,設定TextBox的TextMode=”Multiline”,雙擊Button控制項在其事件下面寫入如下代碼:ValidateRequest="false"
File.AppendAllText("c:/1.txt", TextBox1.Text + "<br />");
2)在View.aspx頁面中加入如下代碼
//Response.Write(File.ReadAllText("c:/1.txt"));
Response.Write(HttpUtility.HtmlEncode(File.ReadAllText("c:/1.txt")));
註:給檔案中寫入<script type=”text/javascript”>alert(‘去韓迎龍的部落格園吧!’);</script>
(5)我們可以對請求的資料做檢測,如果請求資料庫有<等就認為是惡意請求,禁止提交,aspx預設就是採用這種策略,這樣做的缺點是如果做得是一個程式員論壇,程式員就無法發表HTML代碼中的文章了,因此更好的處理策略是將使用者發表的內容按照原樣顯示出來,使用HttpUtility.HtmlEncoding就可以將字串中的<,/等特殊符號轉換為HTML顯示的字元,也就是不把<script>當成定義指令碼的標籤,而是當成”<script>”,這樣可以在頁面上直接顯示出來的內容。
(6) 修改看貼代碼,將context.Response.Write(line+”<hr />”);修改為:
context.Response.Write(HttpUtility.HtmlEncode(line)+”<hr />”);即可。
(7) aspx中預設對請求的資料進行了校正,如果資料中有<./等有潛在XSS攻擊的字元,則會報錯,對於一些CMS系統等確實需要提交HTML內容的地方要關閉它,在頁面頂部的page中加入ValidateRequest="false"這個屬性。
(8) 在顯示的時候如果需要對內容在顯示之前進行HTMLEncode,除了可以使用HttpUtility.HtmlEncode進行手動編碼的話,還可以使用Literal控制項顯示,如果修改Literal的Model屬性為Encode,那麼會自動進行HtmlEncode,然後顯示。
注釋:開發原則2我們就說到這裡了,從下節我們開始說特殊路徑的處理以及Request對象。