电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

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


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

数据复制

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

终止重复数据传输

为了避免那些错误地重复发送给服务器的数据可以在服务器侧进行一些校验来确定用户能 意识到他们正在发送数据这里使用的例子包含一个有单一文本框的简单表单表单接收一些文本然后将其发送到一个显示它们的ASP页 为确保用户不将同样的信息发送两次需要指示数据已经被服务器接收到存储这些信息的最好的地方是一个session变量定义一个session变量Session(submitted) 当用户第一次到达这个表单时将它初始化为False在用户进行最初的数据传输时将它设置为true 如果用户在当前的session期间重新访问这个表单将出现相关重复提交信息

所以用户只能是在有意的情况下向服务器重复发送数据现在来看看执行这一校验的代码建立表单并且校验已发送数据的ASP页(在下载处为formasp)有以下结构

〈 HTML 〉

〈 HEAD 〉

〈 /HEAD 〉

〈 BODY 〉

〈 % If Session(submitted) Then % 〉

〈 ! Code showing the warning message

〈 % Else % 〉

〈 ! Code showing the form

〈 % End If % 〉

〈 /BODY 〉

〈 /HTML 〉

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

〈 FORM METHOD=post ACTION=ManageFormasp

Send me some data:

〈 INPUT TYPE=text NAME=data

〈 P 〉

〈 INPUT TYPE=submit VALUE=Submit

〈 INPUT TYPE=reset VALUE=Cancel

〈 /FORM 〉

ManageFormasp 页接收用户发送的文本显示它并将session 变量submitted设置为True:

〈 HTML 〉

〈 HEAD 〉

〈 /HEAD 〉

〈 BODY 〉

You have sent the following information:

〈 P 〉

〈 %= Request(data) % 〉

〈 % Session(submitted) = True % 〉

〈 /BODY 〉

〈 /HTML 〉

所以当用户又回到这个表单时测试session 变量submitted当它的值为True时发送给用 户的是警告信息而不是输入表单这个警告信息是用HTML和客户机侧的JavaScript代码组合编写的

〈 SCRIPT 〉

function SendAnswer(answer) { documentAnswerFormanswervalue = answer documentAnswerFormsubmit() }

〈 /SCRIPT 〉

You have already submitted some information to this Web site

〈 BR 〉 Do you want submit again?

〈 P 〉

〈 FORM NAME=AnswerForm METHOD=post ACTION=CheckAnswerasp

〈 INPUT TYPE=button VALUE=Yes onClick=SendAnswer('Y')

〈 INPUT TYPE=button VALUE=No onClick=SendAnswer('N')

〈 INPUT TYPE=hidden NAME=answer VALUE=

〈 /FORM 〉

表单包含两个按钮((Yes 和 No) 以及一个隐含控制域(answer) 在其中保存用户所选择的值 Y 或 N这个值由JavaScript 函数SendAnswer() 设置这个函数还将它发送给CheckAnswerasp 页以执行正确的重定向如果用户选择了No按钮CheckAnswerasp 检验隐含控制的值并将其重定向到一个普通 welcome 页反之就将session 变量submitted设置为False 并再次将其重定向到表单页

〈 % If Request(answer) = Y Then Session(submitted) = False ResponseRedirect formasp Else ResponseRedirect End If % 〉

控制浏览器缓沖器

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

〈 % ResponseAddHeader cachecontrol private ResponseAddHeader pragma nocache ResponseExpiresAbsolute = #January ::# ResponseExpires= % 〉

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

多步骤表单

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

避免使用中间步骤表单

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

〈 FORM METHOD=post ACTION=formasp

Your name: 〈 INPUT TYPE=text NAME=name

〈 P 〉

〈 INPUT TYPE=submit VALUE=Submit

〈 INPUT TYPE=reset VALUE=Cancel

〈 /FORM 〉

〈 % Session(requested) = True % 〉

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

〈 % If Session(requested) Then % 〉

〈 HTML 〉

〈 HEAD 〉

〈 /HEAD 〉

〈 BODY 〉

〈 ! Code for the second form

〈 % Session(requested) = True Else ResponseRedirect formasp End If % 〉

〈 /BODY 〉

〈 /HTML 〉

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

结论

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

上一篇:动态提示的下拉框

下一篇:使用Lists