前言任何交互式站点都有一个输入表单,只要有可能,就应该对用户输入的数据进行验证。不管服务器后台是什么样的系统,你都不愿意在一些无效的信息上浪费时间。您必须验证表单数据。如有表单输入不符合要求,应及时返回并给出相应的提示信息。本文将列举四种不同原理的表单验证方法,并给出每种方法在PHP服务器上的实现。浏览器端验证传统上,表单数据通常通过浏览器端Javascript进行验证。浏览器端验证速度快。如果有任何不符合要求的输入,会迅速将响应信息返回给用户。由于验证数据不需要提交给服务器,因此不会增加服务器的负载。一个浏览器端的验证流程如图1所示,提交表单时,如果验证通过,则提交给服务器处理,如果不通过,则返回给用户。图1.浏览器端验证示意图。本文给出的各种表单验证方法的源码均以一个简单的表单为例。该表单包含两个文本输入框“用户名”和“密码”,以及一个“提交”按钮。代码清单1给出了浏览器端Javascript验证的示例。如果“UserName”或“Password”的输入不符合要求,将以弹框形式提示用户,并返回false停止表单提交。清单1.浏览器端Javascript验证代码functionvalidform(thisForm){error_string="";if((message=checkusername(thisForm.username))!=""){error_string="用户名:"error_string+=message;警报(错误字符串);返回假;}if((message=checkpassword(thisForm.pass))!=""){error_string="密码:"error_string+=message;警报(错误字符串);返回假;}返回真;}从图1可以看出,这种表单验证方式有一个致命的缺点。很多工具可以在表单验证后,浏览器发送请求前拦截表单数据。向服务器注入数据,会增加XSS(全称CrossSiteScripting)攻击的概率。对于一般的网站来说,浏览器端的表单验证方式并不受欢迎。浏览器端和服务器端双重验证方式在浏览器端验证方式的基础上增加了服务器端验证方式。原理如图2所示,这种方式增加了服务器端验证,弥补了传统浏览器的不足。端到端身份验证的缺点。如果表单输入不符合要求,浏览器端Javascript验证可以快速响应,而服务端验证可以防止恶意用户绕过Javascript验证,保证最终数据的准确性。图2浏览器端和服务器端双重认证示意图该方法除了客户端Javascript认证外,还增加了服务器端PHP认证。示例代码如清单2所示。checkusername()和checkpassword()是两段用PHP语言编写的代码。验证接口函数根据$error结果判断表单的有效性。清单2.服务器端表单的PHP验证if(isset($_POST['username'])){$usermsg=checkusername($_POST['username']);如果($usermsg!='')$error=true;if(isset($_POST['pass'])){$passmsg=checkpassword($_POST['pass']);如果($passmsg!='')$error=true;这种方式的缺点一目了然,必须维护两段代码才能实现相同的功能,增加了开发人员的工作量,不利于后续开发。浏览器端和服务器端双重验证方式也存在风险。对于一些表单验证规则,服务器可能不想向用户公开,但是浏览器复制了服务器端的验证功能,将验证规则发布给了用户。服务器端验证结合了以上两种验证方式。现在考虑使用服务器端验证方法。该方法的结构非常简单,其原理如图3所示。客户端负责提交表单,服务器端对表单进行验证。如果发现有错误数据,则返回表单页面,并在同一页面添加错误信息。如果验证通过,则处理表单。图3服务端验证示意图当该方法遇到非法输入需要返回表单时,除了加载该页面的错误信息外,还必须注意。这时,表单的内容必须维护表单提交时的用户输入,这样用户才能将错误的表单输入与错误提示信息联系起来,有助于用户填写正确的输入.可以使用DOM技术中的appendChild函数附加显示相关的错误提示信息。其实现如代码清单3所示,效果见图4。清单3.利用DOM技术实现提示信息代码find_obj=document.getElementsByName("username");varsp1=document.createElement('span');sp1.className='formerror';sp1.appendChild(document.createTextNode(usermsg));find_obj[0].parentNode.appendChild(sp1);find_obj=document.getElementsByName("通过");varsp2=document.createElement('span');sp2.className='formerror';sp2.appendChild(document.createTextNode(passmsg));find_obj[0].parentNode.appendChild(sp2);图4加载错误信息的效果由于验证是由服务器端处理的,因此这种方式的输入响应速度没有浏览器端验证快,主要受网络繁忙和服务器负载的影响。同时,如果同一页面的其他表单耗时较长,这种返回页面的方法的响应时间会进一步增加。基于Ajax技术的验证基于Ajax技术的表单验证技术结合了服务器端验证、浏览器端和服务器端双重验证方式的优点,并摒弃了两者的缺点。服务器端验证方式结构清晰,可以防止恶意攻击。主要问题是如果表单信息输入错误,需要整个页面重传。同时,如果同一个页面有多个表单,返回整个页面可能会增加用户的等待时间。浏览器端和服务器端的双因素验证响应很快,但是问题出在代码冗余上。基于Ajax技术的验证方式也需要做两个验证:第一个是反馈验证,无论表单数据是否准确,服务器都会给出反馈信息,相当于双重验证中的浏览器端验证;表单处理前的验证防止恶意修改,其作用相当于双重验证中的服务端验证。其原理如图5所示,表单提交后,首先构建表单信息字段,发送给服务器,由Ajax引擎进行校验。服务器将验证结果发送给用户。客户端根据反馈信息判断表单输入是否正常。在Ajax技术下,对于用户来说,上述操作都在后台运行,不会影响当前页面各个表单的状态。如果是非法输入,将提示信息返回给用户;如果是正常输入,客户端会按照正常的方式提交表单。为了防止恶意修改,在表单处理之前需要进行验证,这一步验证与前面的验证共享代码。图5.基于Ajax的技术验证示意图有关Ajax技术的知识,您可以参考developerWorks上的一系列文章。Ajax的核心概念之一是XMLHttpRequest对象,它是一个JavaScript对象。创建这个对象时,各种浏览器有不同的方法,具体实现可以参考源码。反馈验证主要涉及两个问题:一是构造验证字段,二是反馈信息的格式。由于验证字段与普通表单字段共享验证代码,因此验证字段格式完全遵循表单提交时的格式。为表单构建验证字段的代码如清单4所示。checkflag字段的作用是区分两种类型的验证。清单4.构建验证字段代码varpostData="";varfields=form.elements;for(vari=0;i
