• Effective C# Item39 : 使用.NET验证


        软件开发过程中,安全始终是一个非常重要的话题,如何能保证恶意数据数据不会进入到数据库中,如何使得软件“水火不侵”,经常会成为折磨开发人员的噩梦。保证程序安全的一个重要手段就是对软件的入力数据进行检查,入力数据可能来自于用户直接的手动入力,也可能来自于外部的其他模块,我们需要在业务逻辑执行之前,对数据进行检查,保证只有“正确”的数据才能执行业务逻辑。

        有时执行这种检查是很繁琐的,.NET为我们提供了一些验证机制。针对桌面应用程序和Web应用程序,.NET为我们提供了不同的方式来对数据进行验证。

        针对桌面应用程序,针对需要进行验证的控件,我们需要为其注册Validating事件,在该事件中,编写数据检查的逻辑,同时还需要将控件的CauseValidation属性设置为true,否则,是不会触发Validating事件的。

        我们来看下面的代码。

    Windows Form控件验证
    1 /// <summary>
    2 /// test windows form validation.
    3 /// </summary>
    4   private static void WinFormVailidateTest()
    5 {
    6 Form frmTest = new Form();
    7 TextBox txtName = new TextBox();
    8 txtName.Validating += new System.ComponentModel.CancelEventHandler(txtName_Validating);
    9 frmTest.Controls.Add(txtName);
    10 //test validate with CauseValidation is true.
    11   txtName.CausesValidation = true;
    12 Console.WriteLine("Input With Validation:");
    13 txtName.Text = "aaa";
    14 frmTest.ValidateChildren();
    15 txtName.Text = "aaaaaaa";
    16 frmTest.ValidateChildren();
    17
    18 Console.WriteLine();
    19
    20 //test validate with CauseValidation is false.
    21   txtName.CausesValidation = false;
    22 Console.WriteLine("Input Without Validation:");
    23 txtName.Text = "aaa";
    24 frmTest.ValidateChildren();
    25 txtName.Text = "aaaaaaa";
    26 frmTest.ValidateChildren();
    27 }
    28
    29
    30 /// <summary>
    31 /// textbox's validation event handler.
    32 /// </summary>
    33 /// <param name="sender"></param>
    34 /// <param name="e"></param>
    35   private static void txtName_Validating(object sender, System.ComponentModel.CancelEventArgs e)
    36 {
    37 TextBox txtTemp = sender as TextBox;
    38 if (txtTemp == null || string.IsNullOrEmpty(txtTemp.Text))
    39 {
    40 return;
    41 }
    42
    43 if (txtTemp.Text.Length > 5)
    44 {
    45 Console.WriteLine("Your input is InValid !");
    46 e.Cancel = true;
    47 return;
    48 }
    49 Console.WriteLine("The Text you input is : " + txtTemp.Text);
    50 }

        上面的代码中,我们定义了一个Form和一个TextBox,然后为TextBox控件注册Validating事件,在该事件中,判断如果TextBox中的文本长度超过5,就认为是非法的。然后将TextBox的Text属性设置为不同的值,调用Form的ValidateChildren方法,来触发TextBox的Validating事件。

        上述代码的执行结果如下所示。

        我们可以看到,当将控件的CauseValidation属性设置为false后,是不会触发Validating事件的。

        在上面代码中,我们调用了Form的ValidateChildren方法,该方法会遍历画面中的所有控件,然后调用控件的Validating事件(如果有),当某个控件是一个容器(例如Panel、GroupBox等)时,它会采用递归的方式查找容器中的子控件,下面是针对ValidateChildren方法的一段测试代码,我们将上述的TextBox控件放置到一个Panel中,发现这时TextBox的Validating事件还是可以被触发的。

    代码
    1 /// <summary>
    2 /// test windows form validation for control.
    3 /// test Form.ValidateChildren method.
    4 /// </summary>
    5   private static void ValidateChildrenTest()
    6 {
    7 Form frmTest = new Form();
    8 TextBox txtName = new TextBox();
    9 txtName.Validating += new System.ComponentModel.CancelEventHandler(txtName_Validating);
    10 frmTest.Controls.Add(txtName);
    11 //test validate with textbox is in panel or groupbox that has its own child control.
    12   frmTest.Controls.Remove(txtName);
    13 Panel plTemp = new Panel();
    14 plTemp.Controls.Add(txtName);
    15 frmTest.Controls.Add(plTemp);
    16 txtName.CausesValidation = true;
    17 Console.WriteLine("Validate Control's Input:");
    18 txtName.Text = "aaa";
    19 frmTest.ValidateChildren();
    20 txtName.Text = "aaaaaaa";
    21 frmTest.ValidateChildren();
    22 }

        上述代码的执行结果如下所示。

        我们还可以使用以下的方式遍历画面中的控件,对其进行验证。

    代码
    1 private void ValidateAllChildren( Control parent )
    2 {
    3 // If validation already failed, stop checking.
    4   if( this.DialogResult == DialogResult.None )
    5 return;
    6
    7 // For every control
    8   foreach( Control c in parent.Controls )
    9 {
    10 // Give it focus
    11   c.Focus( );
    12
    13 // Try and validate:
    14   if (!this.Validate( ))
    15 {
    16 // when invalid, don't let the dialog close:
    17   this.DialogResult = DialogResult.None;
    18 return;
    19 }
    20 // Validate children
    21   ValidateAllChildren( c );
    22 }
    23 }
    24  

        下面我们再来看.NET如何对Web应用程序进行验证,.NET提供了5种不同类型的Validator:RequiredFieldValidator、RangeValidator、CompareValidator、RegularExpressionValidator和CustomValidator,其中前三个是比较简单的,第四个需要使用正则表达式,依靠的是正则表达式的强大功能,最后一种CustomValidator是最复杂的一个,我们可以从CustomValidator类中派生一个类,来完成业务自定制的验证,但是一般情况下,我们尽量避免使用CustomValidator,因为CustomValidator在验证时,使用的是脚本,例如JavaScript,这样我们很可能需要使用C#和JavaScript两种语言来编写同样的验证逻辑,一个用于客户端,一个用于服务器端,这样做是比较繁琐的,我们应该尽量使用前四种类型的Validator。

        我们来看前四种Validator如何使用,请看下面的代码。

    Aspx 控件验证
    1 /// <summary>
    2 /// test aspx page validation.
    3 /// </summary>
    4   private static void AspxValidateTest()
    5 {
    6 Page pgTest = new Page();
    7 System.Web.UI.WebControls.TextBox txtName = new System.Web.UI.WebControls.TextBox();
    8 txtName.ID = "txtName";
    9 pgTest.Controls.Add(txtName);
    10 //RequiredFieldValidator
    11 Console.WriteLine("RequiredValidator:");
    12 System.Web.UI.WebControls.RequiredFieldValidator requiredValidator = new System.Web.UI.WebControls.RequiredFieldValidator();
    13 requiredValidator.ID = "requiredValidator";
    14 requiredValidator.ControlToValidate = txtName.ID;
    15 requiredValidator.ErrorMessage = "Required input!";
    16 pgTest.Controls.Add(requiredValidator);
    17 txtName.Text = string.Empty;
    18 Validate(requiredValidator);
    19 txtName.Text = "aaa";
    20 Validate(requiredValidator);
    21
    22 Console.WriteLine();
    23
    24 //RangedValidator
    25 Console.WriteLine("RangeValidator");
    26 System.Web.UI.WebControls.RangeValidator rangeValidator = new System.Web.UI.WebControls.RangeValidator();
    27 rangeValidator.ID = "rangeValidator";
    28 rangeValidator.ControlToValidate = txtName.ID;
    29 rangeValidator.MinimumValue = "a";
    30 rangeValidator.MaximumValue = "z";
    31 rangeValidator.Type = System.Web.UI.WebControls.ValidationDataType.String;
    32 rangeValidator.ErrorMessage = "Out of Range !";
    33 pgTest.Controls.Add(rangeValidator);
    34 txtName.Text = "!@#";
    35 Validate(rangeValidator);
    36 txtName.Text = "a";
    37 Validate(rangeValidator);
    38
    39 Console.WriteLine();
    40
    41 //CompareValidator
    42 Console.WriteLine("CompareValidator:");
    43 System.Web.UI.WebControls.TextBox txtMin = new System.Web.UI.WebControls.TextBox();
    44 txtMin.ID = "txtMin";
    45 System.Web.UI.WebControls.TextBox txtMax = new System.Web.UI.WebControls.TextBox();
    46 txtMax.ID = "txtMax";
    47 pgTest.Controls.Add(txtMax);
    48 pgTest.Controls.Add(txtMin);
    49 System.Web.UI.WebControls.CompareValidator compareValidator = new System.Web.UI.WebControls.CompareValidator();
    50 compareValidator.ID = "compareValidator";
    51 compareValidator.ControlToValidate = txtMin.ID;
    52 compareValidator.ControlToCompare = txtMax.ID;
    53 compareValidator.Operator = System.Web.UI.WebControls.ValidationCompareOperator.LessThan;
    54 compareValidator.ErrorMessage = "Compare Fail !";
    55 pgTest.Controls.Add(compareValidator);
    56 txtMin.Text = "b";
    57 txtMax.Text = "a";
    58 Validate(compareValidator);
    59 txtMax.Text = "c";
    60 Validate(compareValidator);
    61 }
    62
    63 /// <summary>
    64 /// validate with validator.
    65 /// </summary>
    66 /// <param name="validator"></param>
    67 private static void Validate(System.Web.UI.WebControls.BaseValidator validator)
    68 {
    69 if (validator == null)
    70 {
    71 return;
    72 }
    73 validator.Validate();
    74 if (!validator.IsValid)
    75 {
    76 Console.WriteLine(validator.ErrorMessage);
    77 }
    78 else
    79 {
    80 Console.WriteLine("Your Input is Valid!");
    81 }
    82 }

        上述代码,针对四种类型的Validator,都列出了两种情况,第一种情况是验证不通过,第二种情况是验证通过。执行结果如下。


       

        通过上面的介绍,我们应该对.NET中的验证机制有一个大致的了解了,当然,上述提供的代码只是出于说明示范作用,在真实的环境中,情况要更加复杂多变,我们还需要见招拆招,具体问题具体分析。

  • 相关阅读:
    java中4种修饰符访问权限的区别
    Java中List的排序方法
    Hibernate事务
    @Component、@Service、@Constroller
    MySQL查看一个表的创建文本以及删除表某列的索引
    深入Session2
    Tomcat容器的Session管理
    深入Session
    使用spring mvc或者resteasy构建restful服务
    Spring MVC学习回顾
  • 原文地址:https://www.cnblogs.com/wing011203/p/1670799.html
Copyright © 2020-2023  润新知