讓 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