Effective C# 使用.NET驗證

用戶的輸入可能是多種多樣的:你必須在交互式的控件中儘可能的驗證輸入。寫一些用戶輸入驗證可能很做作,而且也有出錯的可能,但還是很有必要的。不能太相信用戶的輸入,用戶可能會輸入任何內容導致異常發生,進而進行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.
ifthis.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框架已經提供的服務,你可以減少你自己的代碼編寫工作。驗證所有用戶的輸入,但要使用已經提供了的高效工具。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章