`

高级表单验证-针对多次提交表单(转)

阅读更多
  每个开发人员面对的困难是预测用户能够或是将要做什么--这对于网络开发人员来说就更为困难,因为他的预测必须考虑到Web的多样性和缺乏真正的session控制机制。如果你已经创建过一个使用表单的ASP应用程序,也许你已经遇到过一些奇怪的问题,如数据传输两次,接收数据不完整,或者用户报告表单显示不正确。尽管你也插入了确认数据所需的所有客户机端和服务器端的脚本,表单仍然会发生许多异常情况。这些异常情况与意外用户行为或浏览器书签的误使用有关。本文将集中解决一些容易引起表单问题的典型情况:用户意外地重复发送数据,在多步骤表单中直接使用中间表单。

数据复制

  通过表单重复发送数据是一个常见的情况,但是它会带来问题。在理想的情况下,用户在一个Web站点遇到一个表单,用正确的数据类型填充它,将它提交给处理数据的服务器,然后作为回应发送给用户一个确认页,这时用户就可以再去做别的。如果用户重新访问前面那一页,使用back按钮,然后无意中再将数据发送一次,那将会出现什么情形呢?如果你没有预料到这一场景并且有所准备,数据就将被重新传送给服务器并且再处理一次。试想这些数据是一份订单或旅馆预约,那将会带来很不愉快的结果。

终止重复数据传输

  为了避免那些错误地重复发送给服务器的数据,可以在服务器侧进行一些校验,来确定用户能意识到他们正在发送数据。这里使用的例子包含一个有单一文本框的简单表单,表单接收一些文本,然后将其发送到一个显示它们的ASP页。为确保用户不将同样的信息发送两次,需要指示数据已经被服务器接收到。存储这些信息的最好的地方是一个session变量。定义一个session变量Session("submitted"),当用户第一次到达这个表单时将它初始化为False,在用户进行最初的数据传输时将它设置为true。如果用户在当前的session期间重新访问这个表单,将出现相关重复提交信息。
所以用户只能是在有意的情况下向服务器重复发送数据。现在来看看执行这一校验的代码。建立表单并且校验已发送数据的ASP页(在下载处为form.asp)有以下结构:
HTML
HEAD
/HEAD
BODY
IfSession("submitted")Then
!--Codeshowingthewarningmessage--
...
Else
!--Codeshowingtheform--
...
EndIf
/BODY
/HTML

  表单和警告信息都是从同一个ASP页创建的。表单包括标准的HTML代码,引用ManageForm.asp页作为它的ACTION属性:

FORMMETHOD="post"ACTION="ManageForm.asp"
Sendmesomedata:
INPUTTYPE="text"NAME="data"
P
INPUTTYPE="submit"VALUE="Submit"
INPUTTYPE="reset"VALUE="Cancel"
/FORM

ManageForm.asp
页接收用户发送的文本,显示它并将session变量submitted设置为True:
HTML
HEAD
/HEAD
BODY
Youhavesentthefollowinginformation:
P
=Request("data")
Session("submitted")=True
/BODY
/HTML

  所以当用户又回到这个表单时,测试session变量submitted,当它的值为True时,发送给用户的是警告信息而不是输入表单。这个警告信息是用HTML和客户机侧的javascript代码组合编写的:
SCRIPT
functionSendAnswer(answer){document.AnswerForm.answer.value=answerdocument.AnswerForm.submit()}
/SCRIPT
YouhavealreadysubmittedsomeinformationtothisWebsite.
BRDoyouwantsubmitagain?
P
FORMNAME="AnswerForm"METHOD="post"ACTION="CheckAnswer.asp"
INPUTTYPE="button"VALUE="Yes"onClick="SendAnswer(Y)"
INPUTTYPE="button"VALUE="No"onClick="SendAnswer(N)"
INPUTTYPE="hidden"NAME="answer"VALUE=""
/FORM

  表单包含两个按钮((YesNo)以及一个隐含控制域(answer),在其中保存用户所选择的值:YN。这个值由javascript函数SendAnswer()设置,这个函数还将它发送给CheckAnswer.asp页以执行正确的重定向。如果用户选择了No按钮,CheckAnswer.asp检验隐含控制的值,并将其重定向到一个普通welcome页,反之就将session变量submitted设置为False并再次将其重定向到表单页。
IfRequest("answer")="Y"ThenSession("submitted")=FalseResponse.Redirect"form.asp"ElseResponse.Redirect"welcome.htm"EndIf

控制浏览器缓冲器

  如果你已经实施了以上方法,你会发现,只有当你在浏览器的地址文本框内键入URL来回到这个表单时,此方法才奏效。它依靠的是浏览器的缓冲器机制。如果你使用back按钮来返回页,浏览器就检测它的缓冲器来找到该页的副本。它将使用缓存的页而不是向服务器发出请求。所以服务器就不能在session变量submitted上进行校验。为了避免这种情况,就要抑制浏览器的页缓冲器。这通过在表单页中处理Response对象来实现。取消页缓冲器有多种方法。所有这些方法都要依靠HTTP头文件中到浏览器的地址指示。但是所有浏览器对服务器发送的指示反应不同,所以说最好能多发送一些指示来为更多的浏览器抑制缓冲器,按以下代码所示:

Response.AddHeader"cache-control","private"Response.AddHeader"pragma","no-cache"Response.ExpiresAbsolute=#January1,199000:00:01#Response.Expires=0

  以上代码的头两行使用Response对象的AddHeader方法来将头信息附加到HTTP头文件中。ExpiresExpiresAbsolute属性用浏览器缓冲器中页的持续时间信息来标记当前页。在表单页中,这些行必须要插入在所有代码之前,因为她们所引用的信息放置在HTTP头文件中,在所有输出之前发送给浏览器。

多步骤表单

  如果一个表单需要许多数据,那么最好将你要求的数据划分成多个小表单,这样使用户可以一步一步地填充表单,而不用等待表单加载许多HTML控制。另外还有一些情况,表单中的某些控制不完全必要,并且可以用已经提交的数据逐行填充。使用多步骤表单允许显示倚赖于用户以前答案的定制表单。如果用户在浏览器中将一个中间表单设置为书签的话就会产生问题。在随后的一个session中,用户就试图直接到达这个表单并提交数据,这些数据已经在上下文范围之外,因为本来应该在前面表单收集的session数据丢失了。

避免使用中间步骤表单

  为了避免这些问题,可以存储当前数据收集的状态。这个状态可以用一个session变量来代表来记录是否执行了一个特定的步骤---用户是否填充了给出的表单。在一个多步骤表单中,每个表单都可以通过一个Boolean型的session变量来实现。如果有关表单没有被处理,变量就为False,反之就是True。下载部分的第二个例子显示一个两步骤表单:第一个表单要求用户名,第二个表单显示一个组合框,它的列表项要依赖第一个表单所提供的用户名。第一个表单与一个session变量requested1相关联,你可以想象出来,第二个表单与变量requested2相关联。当用户要求第一个表单(form1.asp)时,session变量requested1被设置为True:

FORMMETHOD="post"ACTION="form2.asp"
Yourname:
INPUTTYPE="text"NAME="name"
P
INPUTTYPE="submit"VALUE="Submit"
INPUTTYPE="reset"VALUE="Cancel"
/FORM
Session("requested1")=True

  这个值将由下一个表单(form2.asp)来校验,以确定是否满足了要求。事实上当用户要求第二个表单时校验requested1变量。如果为True,就向浏览器发送第二个表单并将requested2变量设置为True。如果为False就意味着用户想要直接使用第二个表单,于是浏览器就重定向到第一个表单。以下代码是第二个表单的ASP页:

IfSession("requested1")Then
HTML
HEAD
/HEAD
BODY
!--Codeforthesecondform--
...
Session("requested2")=TrueElseResponse.Redirect"form1.asp"EndIf
/BODY
/HTML

  要注意对requested1的校验必须要在〈HTML〉记录之前进行,这样就允许可能的重定向。实际上,重定向是对浏览器的指示,它出现在HTTP头文件中,在所有的HTML代码之前。

结论

  本文所示范的两种技巧允许ASP开发人员对某些奇怪的情况有所控制,这些奇怪情况会造成用户通过一个Web表单向服务器重复发送数据。每个技巧解决一个特定问题,所以最好将两者混合使用,在ASP应用程序每个表单中管理两个session变量。
分享到:
评论

相关推荐

    JavaScript表单即时验证 验证不成功不能提交

    不能再让表单在提交按钮之后才被验证了!你输入的任何信息表单都会即时反应! 这个JavaScript的关键是onChange()事件,使用onKeyUp()事件完成是不行的,人家没有输入完毕,你就说人家不对,多不友好啊╮(╯▽╰)╭ ...

    jQ表单万能验证插件 vf-validate.js

    在同一页面下,可直接多次使用属性 vf-name 调用已有的全局规则,调用全局规则时无需加"/g" 7.vf-null (可选)非空验证:yes/no;开启后,若数据为空,则跳过当前数据验证 注: 1.验证的表单元素,需要添加 class ...

    element-ui如何防止重复提交的方法步骤

    先说对话框(Dialog)里的表单提交 错误方案 说起错误方案,比如,点击提交按钮,本地验证,验证通过立即让按钮不可点,这些没问题,而我的错误点概括是:在某个最后执行的回调函数的最后一行,我做了2个操作:1,...

    js验证表单 js验证表单

    js表单验证控制代码大全 /* 目录: 1:js 字符串长度限制、判断字符长度 、js限制输入、限制不能输入、textarea 长度限制 2.:js判断汉字、判断是否汉字 、只能输入汉字 3:js判断是否输入英文、只能输入英文 4:js只能...

    超详细表单验证

    针对表单所有类型进行验证,一次性检验,多类型同步验证

    表单验证大全

    6. 验证油箱格式 [removed] function isEmail(strEmail) { if (strEmail.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1) return true; else alert("oh"); } ...

    PHP经典实例--表单

    讨论了PHP应用程序中处理和验证表单输入、处理多页表单、显示带有错误信息的表单,以及预防跨站点脚本和同一表单多次提交等方面的问题。

    Pisx通用表单验证框架2.0

    这是目前国内开发的所有JS表单验证框架中最好的一个。理由如下:1、简单,只有一个JS文件,不需要其它相关JS支持。2集成AJAX验证支持。3、验证类型全面。4、极易扩展。 主要功能有: PISX通用表单验证具有以下一些...

    TP3.2的简单数据验证php类.zip

    我们在Model中处理数据的时候会一次传入很多参数,这时候可能需要对参数进行判断,是不是少参数了,参数的格式是否正确,如果每次都一大堆if判断的话会很麻烦,以前用过CI,它里面有对form表单提交的数据进行验证的...

    jquery验证插件,脚本验证插件

    支持开启网速慢时的二次提交防御(有时连续的点击提交表单按钮会产生多次的表单提交结果); 指定表单下任一元素在单击时触发表单提交事件; 支持一个页面多表单的检测。例如你给页面上的各form绑定同样的class...

    jquery 表单验证之通过 class验证表单不为空

    class可以多次引用) 1:为input添加class,名字可以随意设置,但每个input需要保持一致,本章案例calss设置为noNull。(若input已有class属性,可直接加到其后) 2:为input添加一个属性,用来后期通过jquery获取该...

    微信小程序防止多次点击跳转和防止表单组件输入内容多次验证功能(函数防抖)

    **函数节流:一个函数执行一次后,只有大于设定的执行周期后才会执行第二次**。有个需要频繁触发函数,出于优化性能角度,在规定时间内,只让函数触发的第一次生效,后面不生效。 ### 1.如何实现 其原理是用时间戳来...

    Jquery表单验证失败后不提交的解决方法

    很多人可能都会遇到在调试的时候用了return了...这个问题我最近也碰到了,尝试了多次也没有用,后来终于发现了其中的问题,下面分享处理给大家,让同样遇到这个问题的朋友们能够看看,有需要的朋友们下面来一起看看吧。

    详解正则表达式表单验证实例

    下面通过一段代码给大家分析表单验证正则表达式,具体代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-"> <title>正则验证常用表单方法</title> &...

    iview同时验证多个表单问题总结

    主要介绍了iview同时验证多个表单问题总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    js禁止表单重复提交

    主要介绍了js禁止表单重复提交的方法,避免重复记录带来的问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    AmazeUI的JS表单验证框架实战示例分享

    本人是小白,以前做表单验证都是在提交之前用js检查一下参数,但这个项目中参数较多,而且同一字段的校验方式不同(队长QQ、手机必填而队员不用),若再用之前的方法工作量显然较大,有没有更好的方法呢?...

    ThinkPHP 防止表单重复提交的方法

    极端的情况,若用户在页面间切换多次,那么多点几次后退按钮很可能又回到了上一个表单页面。 解决办法是在http头中设置Cache-Control: no-cache, no-store。然而我尝试了无论是在页面head中添加 <meta ...

    使用vue中的混入mixin优化表单验证插件问题

    这段时间开发的时候使用到了这个表单校验插件,用起来比较麻烦就不说了,还有较严重的缺陷。自己最终还是抽空把这个插件进行了一些优化,虽然优化的方式和当初...无法在一个组件里面多次使用校验函数,无法自定义校验

    react-components-form:React组件表单使您可以通过使用“ form-schema-validation”进行架构验证来创建表单

    React元件表格v3 特征 同步验证 ...表单元素(您可以使用字段创建组件并多次使用) FieldsRestyle(您可以重新设置所有组件的样式) Bootstrap样式的字段 文献资料 版本^ 3.0.0 版本^ 2.0.0 安装 $

Global site tag (gtag.js) - Google Analytics