让 ASP.NET JS验证和服务端的 双验证 更简单


转自: http://www.cnblogs.com/sunkaixuan/p/4550580.html

只用JavaScript验证安全不安全

谁都知道,答案是不安全,非常的不安全。因为在客户端进行的验证相当于“让用户自己验证自己”,很明显是不靠谱的。你不能避免一些恶意用户人为的修改自己的表单进行欺骗,也不能避免第三方对表单进行截获后进行篡改再提交。

所以说,从安全的角度来说,单纯的依靠js验证,是不安全的,任何健壮的系统都必须在后端进行验证。


双验证大大增加了工作量,如何解决?

方案1:笨方法,都写一遍

方案2:现有框架 ,比如MVC自带验证支持双向验证 ,不足点是要写 model加attrbute 也要有一定工作量

方案3:自已封装


我的选择方案:方案3

思路
page 加载时通过Key去存储表 form规则,通过form规则生成前台元素的绑定,完成前台验证。后台函数通过key在获取表单规则进行后台验证。(可以用缓存机质提高性能)

实现

后台代码:

通过GetInitScript存储form规则并且赋值给 ViewState["intisript"]去前台绑定




前台调用只要绑定 viewState["intiscript"] (其实什么都不要写,保证元素name和 viewstate中一致就可以了):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<body>
     <form id= "form1"  runat= "server"  class = "contact_form" >
     <ul>
         <li>
             <h2>
                 表单验证</h2>
             <span  class = "required_notification" >* 表示必填项</span> </li>
         <li>
             <label  for = "name" >
                 姓名:</label>
             <input type= "text"  name= "name"  />
         </li>
         <li>
             <label>
                 姓别:</label>
             <input type= "radio"  value= "1"  name= "sex"  />男
             <input type= "radio"  value= "0"  name= "sex"  />女 </li>
         <li>
             <label  for = "email" >
                 电子邮件:</label>
             <input type= "email"  name= "email"  />
         </li>
         <li>
             <label  for = "website" >
                 手 机:</label>
             <input type= "text"  name= "phone"  />
         </li>
         <li>
             <label  for = "website" >
                 学 历:</label>
             < select  name= "education"  >
                 <option value= "" >==请选择==</option>
                 <option value= "1" >大学</option>
             </ select >
         </li>
         <li>
             <label  for = "message" >
                 备注:</label>
             <textarea name= "remark"  cols= "40"  rows= "6" ></textarea>
         </li>
         <li></li>
     </ul>
     <br />
     <asp:Button ID= "Button1"  runat= "server"  Text= "submit"  CssClass= "submit"  OnClick= "Button1_Click"  />
     </form>
    <span style= "color: #ff0000;" > <%=ViewState[ "intiscript" ]%></span>
</body>
 
  

  

 ViewState["intiscript"] 将生成一段脚本 给HTML元素添加 pattern、placeholder和requierd 等属性 ,有了这些属性可以很方便的使用JS等插件进行前端验证

下面是通过ViewState["intiscript"] 生成出来的HTML
 
  
1
 
 



后台使用 PostValidation函数进行验证



我们来看看效果:

 
  

 

 


提交成功验证通过了,下面我来改下前端元素采 用恶意参数 提交后台




前台验证通过:


后台还是要把你给揪出来


最后附上C#验证类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Text.RegularExpressions;
 
 
/// <summary>
/// ** 描述:可以方便实现前后端双验证,基于jquery
/// ** 创始时间:2015-6-4
/// ** 修改时间:-
/// ** 作者:sunkaixuan
/// ** 使用说明:-
/// </summary>
public  class  ValidationSugar
{
 
     private  static  List<ValidationOption> ValidationOptionList =  new  List<ValidationOption>();
 
     /// <summary>
     /// 前台注入
     /// </summary>
     /// <param name="pageKey"></param>
     /// <param name="itemList"></param>
     public  static  string  GetInitScript( string  pageKey, List<OptionItem> itemList)
     {
         //初始化后不在赋值
         if  (ValidationOptionList.Any(it => it.PageKey == pageKey))
         {
             return  (ValidationOptionList.Single(c => c.PageKey == pageKey).Script);
         }
         else
         {
             ValidationOption option =  new  ValidationOption();
             string  uk = Guid.NewGuid().ToString().Replace( "-" "" ); //唯一函数名
             string  script =  @"<script>
var bindValidation{1}=function(name,params){{
      var selectorObj=$(""[name='""+name+""']"");
      selectorObj.after(""<span class=\""form_hint\"">""+params.tip+""</span>"");
      if(params.pattern!=null)
      selectorObj.attr(""pattern"",params.pattern);
      if(params.placeholder!=null)
      selectorObj.attr(""placeholder"",params.placeholder);
      if(params.isRequired=true)
      selectorObj.attr(""required"",params.isRequired);
}}
 
 
 
{0}</script>" ;
             StringBuilder itemsCode =  new  StringBuilder();
             foreach  ( var  item  in  itemList)
             {
                 switch  (item.Type)
                 {
                     case  OptioItemType.Mail:
                         item.Pattern =  @"^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$" ;
                         break ;
                     case  OptioItemType.Int:
                         item.Pattern =  @"^\\d{1,11}$" ;
                         break ;
                     case  OptioItemType.Double:
                         item.Pattern =  @"^\\d{1,11}$" ;
                         break ;
                     case  OptioItemType.IdCard:
                         item.Pattern =  @"^(\\d{15}$|^\\d{18}$|^\\d{17}(\\d|X|x))$" ;
                         break ;
                     case  OptioItemType.Date:
                         item.Pattern =  @"^(((1[8-9]\\d{2})|([2-9]\\d{3}))([-\\/])(10|12|0?[13578])([-\\/])(3[01]|[12][0-9]|0?[1-9])$)|(^((1[8-9]\\d{2})|([2-9]\\d{3}))([-\\/])(11|0?[469])([-\\/])(30|[12][0-9]|0?[1-9])$)|(^((1[8-9]\\d{2})|([2-9]\\d{3}))([-\\/])(0?2)([-\\/])(2[0-8]|1[0-9]|0?[1-9])$)|(^([2468][048]00)([-\\/])(0?2)([-\\/])(29)$)|(^([3579][26]00)([-\\/])(0?2)([-\\/])(29)$)|(^([1][89][0][48])([-\\/])(0?2)([-\\/])(29)$)|(^([2-9][0-9][0][48])([-\\/])(0?2)([-\\/])(29)$)|(^([1][89][2468][048])([-\\/])(0?2)([-\\/])(29)$)|(^([2-9][0-9][2468][048])([-\\/])(0?2)([-\\/])(29)$)|(^([1][89][13579][26])([-\\/])(0?2)([-\\/])(29)$)|(^([2-9][0-9][13579][26])([-\\/])(0?2)([-\\/])(29))|(((((0[13578])|([13578])|(1[02]))[\\-\\/\\s]?((0[1-9])|([1-9])|([1-2][0-9])|(3[01])))|((([469])|(11))[\\-\\/\\s]?((0[1-9])|([1-9])|([1-2][0-9])|(30)))|((02|2)[\\-\\/\\s]?((0[1-9])|([1-9])|([1-2][0-9]))))[\\-\\/\\s]?\\d{4})(\\s(((0[1-9])|([1-9])|(1[0-2]))\\:([0-5][0-9])((\\s)|(\\:([0-5][0-9])\\s))([AM|PM|am|pm]{2,2})))?$" ;
                         break ;
                     case  OptioItemType.Mobile:
                         item.Pattern =  @"^[0-9]{11}$" ;
                         break ;
                     case  OptioItemType.Telephone:
                         item.Pattern =  @"^(\\(\\d{3,4}\\)|\\d{3,4}-|\\s)?\\d{8}$" ;
                         break ;
                     case  OptioItemType.Fax:
                         item.Pattern =  @"^[+]{0,1}(\\d){1,3}[ ]?([-]?((\\d)|[ ]){1,12})+$" ;
                         break ;
                     case  OptioItemType.Regex:
                         break ;
                 }
                 itemsCode.AppendFormat( "bindValidation{0}('{1}',{{   tip:'{2}',pattern:'{3}',placeholder:'{4}',isRequired:{5} }})" , uk, item.FormFiledName, item.Tip, item.Pattern, item.Placeholder, item.IsRequired ?  "true"  "false" );
                 itemsCode.AppendLine();
             }
             option.Script =  string .Format(script, itemsCode.ToString(), uk);
             script =  null ;
             itemsCode.Clear();
             option.PageKey = pageKey;
             option.ItemList = itemList;
             ValidationOptionList.Add(option);
             return  (option.Script);
         }
     }
 
     /// <summary>
     /// 后台验证
     /// </summary>
     /// <param name="pageKey"></param>
     /// <param name="errorMessage">json格式</param>
     /// <returns></returns>
     public  static  bool  PostValidation( string  pageKey,  out  string  errorMessage)
     {
         bool  isSuccess =  true ;
         errorMessage =  string .Empty;
         if  (!ValidationOptionList.Any(c => c.PageKey == pageKey))
         {
             throw  new  ArgumentNullException( "ValidationSugar.PostValidation.pageKey" );
         }
         var  context = System.Web.HttpContext.Current;
         var  itemList = ValidationOptionList.Where(c => c.PageKey == pageKey).Single().ItemList;
         var  successItemList = itemList.Where(it => (it.IsRequired && ! string .IsNullOrEmpty(context.Request[it.FormFiledName]) || !it.IsRequired)).Where(it => Regex.IsMatch(context.Request[it.FormFiledName], it.Pattern.Replace( @"\\" @"\" ))).ToList();
         isSuccess = (successItemList.Count == itemList.Count);
         if  (!isSuccess)
         {
             errorMessage =  new  System.Web.Script.Serialization.JavaScriptSerializer().Serialize(itemList);
         }
         return  isSuccess;
     }
 
 
     private  class  ValidationOption
     {
         public  string  PageKey {  get set ; }
         public  string  Script {  get set ; }
         public  List<OptionItem> ItemList {  get set ; }
 
     }
 
     public  enum  OptioItemType
     {
         Mail = 0,
         Int = 2,
         Double = 3,
         IdCard = 4,
         Date = 5,
         /// <summary>
         /// 移动电话
         /// </summary>
         Mobile = 6,
         /// <summary>
         /// 座机
         /// </summary>
         Telephone = 7,
         Fax = 8,
         /// <summary>
         /// 没有合适的,请使用正则验证
         /// </summary>
         Regex = 1000
 
     }
     /// <summary>
     /// 验证选项
     /// </summary>
     public  class  OptionItem
     {
         /// <summary>
         /// 验证类型
         /// </summary>
         public  OptioItemType Type {  get set ; }
         /// <summary>
         /// 正则
         /// </summary>
         public  string  Pattern {  get set ; }
         /// <summary>
         /// 是否必填
         /// </summary>
         public  bool  IsRequired {  get set ; }
         /// <summary>
         /// 表单字段名(name或者id)
         /// </summary>
         public  string  FormFiledName {  get set ; }
         /// <summary>
         /// 水印
         /// </summary>
         public  string  Placeholder {  get set ; }
         /// <summary>
         /// 提醒
         /// </summary>
         public  string  Tip {  get set ; }
 
     }
}

  


源码下载:http://pan.baidu.com/s/1mgoXpsW

时间问题只支持HTML5验证,需要高版本浏览器,以后我会慢慢完善


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM