zoukankan      html  css  js  c++  java
  • 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中的验证机制有一个大致的了解了,当然,上述提供的代码只是出于说明示范作用,在真实的环境中,情况要更加复杂多变,我们还需要见招拆招,具体问题具体分析。

  • 相关阅读:
    2017ccpc全国邀请赛(湖南湘潭) E. Partial Sum
    Codeforces Round #412 C. Success Rate (rated, Div. 2, base on VK Cup 2017 Round 3)
    2017 中国大学生程序设计竞赛 女生专场 Building Shops (hdu6024)
    51nod 1084 矩阵取数问题 V2
    Power收集
    红色的幻想乡
    Koishi Loves Segments
    Wood Processing
    整数对
    Room and Moor
  • 原文地址:https://www.cnblogs.com/wing011203/p/1670799.html
Copyright © 2011-2022 走看看