让 ASP.NET JS验证和服务端的 双验证 更简单
2015-06-03 23:12
696 查看
[b]只用JavaScript验证安全不安全 [/b] 谁都知道,答案是不安全,非常的不安全。因为在客户端进行的验证相当于“让用户自己验证自己”,很明显是不靠谱的。你不能避免一些恶意用户人为的修改自己的表单进行欺骗,也不能避免第三方对表单进行截获后进行篡改再提交。 所以说,从安全的角度来说,单纯的依靠js验证,是不安全的,任何健壮的系统都必须在后端进行验证。 [b]双验证大大增加了工作量,如何解决? [/b]方案1:笨方法,都写一遍 方案2:现有框架,比如MVC自带验证支持双向验证,不足点是要写model加attrbute也要有一定工作量 方案3:自已封装 [b]我的选择方案:方案3 思路 [/b]page加载时通过Key去存储表form规则,通过form规则生成前台元素的绑定,完成前台验证。后台函数通过key在获取表单规则进行后台验证。(可以用缓存机质提高性能) 实现 后台代码: 通过GetInitScript存储form规则并且赋值给ViewState["intisript"]去前台绑定前台调用只要绑定viewState["intiscript"](其实什么都不要写,保证元素name和viewstate中一致就可以了):
ViewState["intiscript"]将生成一段脚本给HTML元素添加pattern、placeholder和requierd等属性,有了这些属性可以很方便的使用JS等插件进行前端验证 下面是通过ViewState["intiscript"]生成出来的HTML
后台使用PostValidation函数进行验证
我们来看看效果:
提交成功验证通过了,下面我来改下前端元素采用恶意参数提交后台
前台验证通过:
后台还是要把你给揪出来
[b]最后附上C#验证类代码:[/b]
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Text.RegularExpressions;namespaceSyntacticSugar
{
///<summary>
///**描述:可以方便实现前后端双验证,基于jquery
///**创始时间:2015-6-4
///**修改时间:-
///**作者:sunkaixuan
///**使用说明:http://www.cnblogs.com/sunkaixuan/p/4550580.html
///</summary>
publicclassValidationSugar
{privatestaticList<ValidationOption>ValidationOptionList=newList<ValidationOption>();///<summary>
///前台注入
///</summary>
///<paramname="pageKey"></param>
///<paramname="itemList"></param>
publicstaticstringGetInitScript(stringpageKey,List<OptionItem>itemList)
{
//初始化后不在赋值
if(ValidationOptionList.Any(it=>it.PageKey==pageKey))
{
return(ValidationOptionList.Single(c=>c.PageKey==pageKey).Script);
}
else
{
ValidationOptionoption=newValidationOption();
stringuk=Guid.NewGuid().ToString().Replace("-","");//唯一函数名
stringscript=@"<script>
varbindValidation{1}=function(name,params){{
varselectorObj=$(""[name='""+name+""']"");
selectorObj.after(""<spanclass=\""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>";
StringBuilderitemsCode=newStringBuilder();
foreach(variteminitemList)
{
switch(item.Type)
{
caseOptionItemType.Mail:
item.Pattern=@"^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$";
break;
caseOptionItemType.Int:
item.Pattern=@"^\\d{1,11}$";
break;
caseOptionItemType.Double:
item.Pattern=@"^\\d{1,11}$";
break;
caseOptionItemType.IdCard:
item.Pattern=@"^(\\d{15}$|^\\d{18}$|^\\d{17}(\\d|X|x))$";
break;
caseOptionItemType.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;
caseOptionItemType.Mobile:
item.Pattern=@"^[0-9]{11}$";
break;
caseOptionItemType.Telephone:
item.Pattern=@"^(\\(\\d{3,4}\\)|\\d{3,4}-|\\s)?\\d{8}$";
break;
caseOptionItemType.Fax:
item.Pattern=@"^[+]{0,1}(\\d){1,3}[]?([-]?((\\d)|[]){1,12})+$";
break;
caseOptionItemType.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>
///<paramname="pageKey"></param>
///<paramname="errorMessage">json格式</param>
///<returns></returns>
publicstaticboolPostValidation(stringpageKey,outstringerrorMessage)
{
boolisSuccess=true;
errorMessage=string.Empty;
if(!ValidationOptionList.Any(c=>c.PageKey==pageKey))
{
thrownewArgumentNullException("ValidationSugar.PostValidation.pageKey");
}
varcontext=System.Web.HttpContext.Current;
varitemList=ValidationOptionList.Where(c=>c.PageKey==pageKey).Single().ItemList;
varsuccessItemList=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=newSystem.Web.Script.Serialization.JavaScriptSerializer().Serialize(itemList);
}
returnisSuccess;
}privateclassValidationOption
{
publicstringPageKey{get;set;}
publicstringScript{get;set;}
publicList<OptionItem>ItemList{get;set;}}publicenumOptionItemType
{
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>
publicclassOptionItem
{
///<summary>
///验证类型
///</summary>
publicOptionItemTypeType{get;set;}
///<summary>
///正则
///</summary>
publicstringPattern{get;set;}
///<summary>
///是否必填
///</summary>
publicboolIsRequired{get;set;}
///<summary>
///表单字段名(name或者id)
///</summary>
publicstringFormFiledName{get;set;}
///<summary>
///水印
///</summary>
publicstringPlaceholder{get;set;}
///<summary>
///提醒
///</summary>
publicstringTip{get;set;}}
}
}
[b]源码下载:http://pan.baidu.com/s/1mgoXpsW[/b]时间问题只支持HTML5验证,需要高版本浏览器,以后我会慢慢完善
相关文章推荐
- Asp.net--数据绑定控件Repeater
- [Asp.net 5] Logging-日志系统的基本架构(上)
- ABP(现代ASP.NET样板开发框架)系列之6、ABP依赖注入
- ASP.NET MVC与WebForm区别
- asp中Scripting.Dictionary字典对象使用示例
- 关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案
- Asp.Net alert弹出提示信息的5种方法
- 树莓派(raspberry)使用经验————设置有线和无线ip
- 【ASP.NET北大青鸟】-总结(一)
- asp ODBC 驱动程序不支持所需的属性
- ASP.NET 状态服务 及 session丢失问题解决方案总结
- 通过ASP.NET StateServer实现进程外Session存储
- ASP.NET(C#)实现页面计时(定时)自动跳转
- 【转】asp.net中@page指令的属性Inherits、Src、CodeBehind区别
- Asp.net MVC中的ViewData与ViewBag
- ASP.NET实现TreeView的XML数据源绑定实例代码
- KafkaSpout之PartitionManager
- [Asp.net 5] Logging-新日志系统目录
- asp.net代码操作xml示例
- AspNet MVC4 教学-23:Asp.Net MVC4 Display And Editor 模板技术快速应用Demo