用戶的輸入可能是多種多樣的:你必須在交互式的控件中盡可能的驗證輸入 。寫一些用戶輸入驗證可能很做作,而且也有出錯的可能,但還是很有必要的。 不能太相信用戶的輸入,用戶可能會輸入任何內容導致異常發生,進而進行SQL 注入式攻擊。我們不希望任何類似這樣的事情發生。你應該了解足夠的信息來懷 疑用戶的輸入。很好,每個人都應該這樣做,這也就是為什麼.Net框架已經擴展 了這樣的功能,你可以使用這些功能從而使自己的代碼編寫工作減到最小,因為 我們要對用戶輸入的每一塊數據都要進行驗證。
.Net框架提供了不同的 機制來驗證用戶的輸入,分別可以用在Web和Windows應用程序中。Web應用程序 應該在浏覽器上進行數據驗證,一般是使用JavaScript。一些驗證控件在HTML面 而中生成一些JS代碼,這對你的用戶來說是很有效的:在對每一項輸入時,他們 不用每次返回數據到服務上。這些Web控件是使用正則表達式的擴展功能來完成 對用戶輸入的驗證,這些驗證可以在頁面提交到服務器之間完成。即使如此,你 還是要在服務器上做一些額外的驗證,以免受到程序式的攻擊。Windows就用程 序使用不同的模式。用戶的輸入可以直接在應用程序中用C#代碼來驗證。所有的 Windows控件都是可驗證的,當你想通知用戶的非法輸入時。一般的模式是使用 屬性訪問時的異常來指示非法的輸入。UI控件捕獲這些異常然後顯示錯誤給用戶 。
你可以使用5個web控件來處理ASP.net應用程序中的大多數驗證任務。 這5個控件都是由屬性來控制這些要驗證的特殊的字段。 RequiredFieldValidator 強制用戶在給定字段中輸入一個值,RangeValidator 要求特殊的字段提供的值在給定范圍內,這個范圍可是一個數的大小,也可以是 一個字符串的長度。CompareValidator 可以讓你構造一個驗證規則來驗證表單 上兩個同的控件。這三個控件都很簡單。最後兩個控件提供了強大的功能,可以 讓你根據你想要求的方法進行驗證。RegularExpression 驗證使用與此同時表達 式來驗證用戶的輸入。如果與比較返回匹配,輸入的就是合法的。正則表達式是 很有用的語言。你可以為你所有的實際情況創建正則表達式。VS.net包含了一些 驗證的表達式,這可以幫助你開始學習它。這有一些幫助你學習更多正則表達式 的有用資料,而且我強烈鼓勵你學習它。但我不能跑題而不給你提供一些最常用 的構造。表5.1顯示了最常用的一些正則表達式元素,你可能會在你的應用程序 中用來驗證輸入:
表5.1 常用的正則表達式
構造含意
[a -z]匹配單個小寫字符。括號內的字符集中的任何字符與單個字符匹配。
\d任何數字。
^,$^表示串的開始, $表示結束。
\w匹配任何 單詞.這是[A-Za-z0-9]簡寫。
(?NamedGroup\d{4,16})顯示兩個不同的常 用元素,?NamedGroup 定義了一個特殊的變量來引用匹配。{4,16}匹配前面的構 造至少4次最多16次。這一模式匹配一個至少包含4個但不超過16個數字的字符串 。如果匹配存在,那麼結果會存儲在NamedGroup中以便後面使用。
(a|b|c)匹配a或b或c。 用堅線分開的是選擇操作:輸入的可是其中的任何一個 。
(?(NamedGroup)a|b) 可選的。這與C#裡的三元操作等效,也就是說, 如果NamedGroup 存在,匹配a,否則匹配b.
(譯注,關於正則表達式這裡 只是簡單的說明了一下。覺得作者在這裡寫正則表達式很是不倫不類,即不全也 不精。)
使用這些及正則表達式的構造,你可以發現你可以驗證用戶提交 給你的任何內容。如果正則表達式還不夠,你還可以通過從CustomValidator 派 生一個新在類添加你自己的驗證。這是一個不小的工作,而且我盡可能的避免它 。當你用C#寫了一服務器函數來驗證數據後,還要用ECMAscript寫一個客戶端的 驗證函數。我討厭同樣的事做兩遍,而且我也盡可能的避免用ECMAscript寫任何 內容,所以,我喜歡粘貼正則表達式式。
例如,這有一個正則表達式, 用於驗證US的電話號碼。它接受區號用括號括起來的,或者沒有括號的,然後就 是區號和號碼之間的空格,交換局號(exchange ),以及號碼。區號和交換局號 之間的橫線也是可選的:
((\(\s*\d{3}\s*\))|(\d{3}))-?\s*\d{3}\s*-\s*\d{4}
通過查驗每一個組的表達式,這樣的邏輯是很清楚的:
((\(\s*\d{3}\s*\))|(\d{3}))-?
這和區號匹配,它充許(XXX)或者XXX的形式,其中 XXX是三個數字。任何在數字周圍的空白字符是充許的。最後兩個字符,-和?, 是許可但不要求一個橫線。
剩下的部份用於匹配電話的XXX-XXXX部份。\s匹配任意的空白,\d{3}匹配三個數字,\s*-\s*匹配一個圍繞在數字邊上的空白字符。最後,\d{4}精確匹配4個數字。
windows驗證工作方法小有不同,你 沒有預先的驗證分析。相反,你要寫一個事件句柄到 System.Windows.Forms.Control.Validating事件上,或者,如果你創建了你自 己的控件,重載OnValidating方法(參見原則35)。下面是一個標准的方法:
private void textBoxName_Validating( object sender,
System.ComponentModel.CancelEventArgs e )
{
string error = null;
// Perform your test
if ( textBoxName.Text.Length == 0 )
{
// If the test fails, set the error string
// and cancel the validation event.
error = "Please enter a name";
e.Cancel = true;
}
// Update the state of an error provider with
// the correct error text. Set to null for no
// error.
this.errorProviderAll.SetError( textBoxName, error );
}
你有幾個小工作要完成,以確保沒有不合法的輸入愉愉的混過去 了。每一個控件包含一個CausesValidation屬性,這個屬性決定這個控件是否參 與驗證。一般情況,你應該讓所有控件的這一屬性為真,除非是Cancel按鈕。如 果你忘記了,用戶還必須輸出正確的值以後才能取消對話框。第二個小任務是添 加OK句柄來強制驗證所有的控件。驗證只有在用戶訪問和離開控件時觸發。如果 用戶打開了一個窗口,然後馬上點OK,你的所有驗證代碼都不會執行。為了修正 這個,你要添加OK按鈕句柄,來訪問所有的控件,然後強制驗證它們。下面兩個 常規方法顯示了如何正確的完成任務。遞歸方法處理控件以及它所包含的控件: Tab頁面,控件組以及控件面板:
private void buttonOK_Click( object sender,
System.EventArgs e )
{
// Validate everyone:
// Here, this.DialogResult will be set to
// DialogResult.OK
ValidateAllChildren( this );
}
private void ValidateAllChildren( Control parent )
{
// If validation already failed, stop checking.
if( this.DialogResult == DialogResult.None )
return;
// For every control
foreach( Control c in parent.Controls )
{
// Give it focus
c.Focus( );
// Try and validate:
if (!this.Validate( ))
{
// when invalid, don't let the dialog close:
this.DialogResult = DialogResult.None;
return;
}
// Validate children
ValidateAllChildren( c );
}
}
這些代碼可以處理大多數情況。一個特殊的快捷應 用就是DataGrid/DataSet的組合。在設計時指定ErrorProvider的DataSource以 及DataMember屬性:
ErrProvider.DataSource = myDataSet;
ErrProvider.DataMember = "Table1";
或者在運行 時,調用BindToDataAndErrors 方法來同時設置:
ErrProvider.BindToDataAndErrors( myDataSet, "Table1" );
錯誤會在設置DataRow.RowError 屬性以 及調用DataRow.SetColumnError 方法時顯示特殊的錯誤。ErrorProvider 會在 DataGrid的原始的行上的特殊單元格裡顯示紅色的警告圖標。
大概的了 解(whirlwind tour)了一下.net框架裡的控件驗證,這可能對你很有幫助,在很 多應用程序中,你都可以創建出你所須要的高效驗證。用戶的輸入不能完全信任 :用戶可能會出現錯誤,而且有時會有一些惡意的用戶試圖破壞你的應用程序。 通過.Net框架已經提供的服務,你可以減少你自己的代碼編寫工作。驗證所有用 戶的輸入,但要使用已經提供了的高效工具。
返回教程目錄