使用JSP标签库验证用户的输入(1)
在任何一个需要验证用户提交的逻辑请求的WEB程序中,程序的创建者能够使用两种方法来检查数据信息。第一个方法是在客户端上进行验证,甚至是在请求提交到服务器之前就能完成验证。通常,这个是使用运行在客户端浏览器的JavaScript脚本语言来完成。当表单被提交的时候,脚本就会检查所有提交的内容,如果发现错误,脚本就会弹出一个POPUP窗口来显示错误的信息。第二种方法是在服务器端进行验证的工作,这种方法是在使用应用服务器所支持的技术来执行任何数据操作之前发生的。
服务器的验证方式加重了服务器的负担,但是给予程序员更多的控制权,保证了数据的检查。客户端的验证方式不能保证所有数据的检查,因为某些用户通过在浏览器禁用了JavaScript脚本,因此有些提交的信息无法被检查。但是客户端验证方式比服务器验证方式更快,因为用户不必将验证数据提交到服务器和从服务器得到该页面。
目前,越来越多的在线程序需要服务器端进行验证,主要是因为它保证了检查,提高了程序的安全性。而且近年来的服务器硬件和软件性能有了飞速发展,能够允许更大弹性的程序运行在上,从而更容易的执行它们。
在这篇文章中,我将使用一种独特的方式来进行服务器端验证,这种方式是使用JAVA JSP标签库。然后我会简要的讲叙JSP标签的创建。我的上一篇文章《观点:在WEB应用中使用MVC模式》(译者注:该文已经翻译并在csdn文档中心发表)中创建了一个WEB程序,一个小型项目,它通过用户提交的一个城市名或者邮政编码来显示了当地的天气信息。这个程序完全遵循MVC架构,使用的应用服务器是Tomcat。
验证过程
在一个企业级的应用程序中,数据的验证是一个需要安全性的过程。程序不仅必须匹配空的或者填写不完全的域(field),而且还必须严格小心那些填写错误的表项(entry)。如果数据通过SQL语句被提交并保存到一个RDBMS或者任何一个永久的存储设备中,那么用户能够意外地(或者有意的)提交一个错误的数据,从而导致了无效的SQL语句发生。如果一个恶意的用户能提交空的字符串或者在一个表单中输入特定的数据来执行一个原本只有WEB程序开发者才能执行的操作,将是多么的危险。例如:他们能够从数据库中输出一行数据或者一个表里的数据,甚至可以从数据库中得到他们所想要的敏感信息。
在上文的“在线天气程序”中执行验证的JSP页面是MVC设计中的“视图(VIEW)”角色。每个JSP视图要么提交数据,要么显示数据。当表单中的邮政编码或城市名被提交后,信息被传送给服务器。服务器扮演了MVC中的“控制器(CONTROLER)”角色,由一个Servlet控制器对象来执行从JSP里传递来的行为,并重新定位到下一个视图。更多详细内容在后面将会介绍,让我们先来看看JSP标签的工作机制。
JSP标签
你能够将JSP标签认为是在能够运行Java程序的服务器上所执行的一种定制行为。在JSP中,一个标签看起来很象一个标准的HTML标签。但是,它的逻辑不在客户端被执行,而是由服务器端的Servlet来转换。每个标签被封装到一个独立的类,它的名字和参数属性被一个特殊的.tld扩展名的部署描叙文件中来指出。这个文件应该放置在应用服务器的WEB程序根目录下的WEB-INF 目录中,在JSP中使用 <%@taglib ... %> 来指明,同时也存在于一个a web.xml文件中。当一个JSP引擎遇到一个定制的标签时,它首先检查看是否知道这个标签类的物理位置。如果它知道,就会执行标签类中响应的代码。标签类通常被制作成一个JAR文件,放置在WEB-INF目录下的lib目录中。
Ex. ..\WEB-INF\mytags.tld - 部署描叙文件
Ex. ..\WEB-INF\lib\mytags.jar 标签库(或一个完整目录结构)
为了演示如何使用标签库验证,我已经创建了一个名为notValidZip的定制JSP标签来验证这个邮政编码域(field)。然而,标签能够执行一些行为,比如HTML格式化,域操纵,甚至是数据库查询等。为了另一个检查,我使用了一个来自Coldbeans Software (http://www.servletsuite.com)的标签库,这个库是对于非商业用途来说是免费提供的,它在HTML表单域验证上有许多非常实用的标签。如果你需要在一个商业站点上使用这些标签库,你能够自己写或者购买它们。
以下是部署文件validtag.tld 的部分代码,它用来处理我的notValidZip标签:
<tag>
<name>notValidZip</name>
<tagclass>com.cj.valid.notValidZip</tagclass>
<bodycontent>JSP</bodycontent>
<info>tests zip code</info>
<attribute>
<name>value</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>length</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
它指出标签库名字为 notValidZip,代码在com.cj.valid.notValidZip 类中,而且有两个属性,一个是必需的,一个是可选的。
要让WEB程序知道我们包含了一个定制的标签库,我将它的信息添加到 web.xml 部署描叙文件中。以下是代码:
<taglib>
<taglib-uri>/WEB-INF/validtag.tld</taglib-uri>
<taglib-location>/WEB-INF/validtag.tld</taglib-location>
</taglib>
最后,要在JSP中包含这个标签库,我在我的JSP页面开头加入以下一行:
<%@ taglib uri="/WEB-INF/validtag.tld" prefix="valTag" %>
现在,我可以使用来自那个包的任何标签了,方法为写上它的 <prefix> : <tag name>;比如:
<valTag:notValidZip value="<%=request.getParameter(\"ZIP\")%>">
<!-- body -->
</valTag:notValidZip>
标签通常有一个标签体(body)和可选的属性(attributes)。
<valTag:tagname attribute1="value1" attribute2="value2">
<!-- body -->
</valTag:tagname>
也有些标签没有标签体,比如 <valTag:tagname />
在定义一个标签库时,你能写入所需要的任何前缀(prefix),但是标签名必须匹配tld文件中的名字。
如我所说,实际的验证逻辑在一个称为 "notValidZip"的JAVA类中来实现,它位于一个JAR文件中。这个标签类扩展了TagSupport 粗象类,且导入了javax.servlet.jsp.JspException,javax.servlet.jsp.tagext. 标签和javax.servlet.jsp.tagext.TagSupport 类。主要的行为逻辑在doStartTag() 方法中,当JSP引擎遇到我的新标签时会调用它。
这个方法返回的整数告诉JSP引擎是否应该执行标签体。 请看文章结尾的Listing 1 。
现在,让我们来回顾一下。首先,我写了这个标签类,将它放入“lib”目录下的JAR文件,然后为标签创建了一个部署描叙文件,将它的位置更新到web.xml文件中,在JSP中通过在taglib指示中包含它来使用这个标签。如果我需要验证多个地方的邮政编码,那么我需要做的也就是在多个页面中包含我的标签。请看文章结尾的Listing 2。
Translated by Willpower,2004.1.4