现在,给出一个较完整的例子,全面说明数据验证要做的工作。在这个例子里,用户通过表单提交数据,通过验证后,写入数据库,并给出成功提示,否则给出失败提示。为了使代码简单,让用户只提交一项:用户名。
所有这些工作,都在post.asp这一个程序中完成,利用Request.ServerVariables("REQUEST_METHOD")="POST"来判断表单是否提交,分别进行处理。自定义函数放在另一个文件(myfunction,asp)中,以便重复使用。
首先分析一下,在验证的过程中,要做的工作。
用户提交的用户名是字符型数据,允许用户输入任何字符,所以只需验证其是否为空,以及长度是否符合要求。
要防止重复提交。用户可能通过不断点击“提交”按钮,或是当出现操作成功提示时刷新页面。为此,做下面两个工作:一是利用一段javascript,当提交按钮按下后,将其设为disabled;二是利用一个session来判断是否重复提交表单:在页面初始化的时候传一个session,操作成功时,清空这个session。表单提交后验证这个session,如果为空,说明是重复提交。(session会增加系统的开销,所以我一直不能肯定这是个好办法,你有更好的办法吗?)
要防止伪造的表单。居心不良的人会伪造表单,以绕过你通过HTML或是JS设置的输入条件,所以我不用JS做数据验证。利用自定义函数ChkPost()来判断数据的来源。
以下是post.asp的代码(其中第一行是include数据库连接文件,该文件代码在此略去):
<!--#include file="myconn.asp"-->
<!--#include file="myfunction.asp"-->
<%
'****************************************************************************************
'* NAME:post.asp *
'* CODE:WWW.NETOP.CC *
'* USE:数据验证完整示例 *
'* TIME:2005.7 *
'****************************************************************************************
Response.Buffer = true
Dim UserName
Response.Write "<html><body>"
'======***表单提交后:***======
if Request.ServerVariables("REQUEST_METHOD")="POST" then
Dim founderr,callform,msg
founderr = false '是否有错误发生
callform = false '是否调用表单
msg = "" '提示信息
'=======================================数据验证开始=================================
if ChkPost() = false then
msg = "<li>请勿从外部提交数据!</li>"
founderr = true
callform = false
elseif session("redo") = "" then
msg = msg + "<li>请勿重复提交!</li>"
founderr = true
callform = false
else
UserName = trim(Request.Form("uname"))
if UserName = "" then
msg = msg + "<li>请填写姓名"
founderr = true
callform = true
elseif strLength(username) > 10 then
msg = msg + "<li>姓名长度超过限制"
founderr = true
callform = true
end if
end if
'=======================================数据验证结束=================================
'=======================================数据处理开始=================================
if founderr = true then
'错误处理(当callform=true时调用表单,此时提示信息与表单同时显示,便于用户修正错误)
call message("500")
if callform = true then call myform()
else
'写库开始(MyConn为myconn.asp中创建的Connection对象)
ON ERROR RESUME NEXT
MyConn.BeginTrans '事务处理
'AddNew方法写库
Dim MyRst,sqlStr
set MyRst=server.createobject("adodb.recordset")
MyRst.Open "[userinfo]",MyConn,0,3
MyRst.AddNew
MyRst("username").Value = UserName
MyRst.Update
MyRst.Close
Set MyRst = Nothing
'也可使用insert语句,注意此时要调用SQLEncode()
'MyConn.Execute("insert into [uerinfo] (username)_
' values ('"& SQLEncode(username) &"')")
'显示结果
if MyConn.Errors.count = 0 then
msg = "<li>操作成功!"
call message("500")
MyConn.CommitTrans
session("redo") = ""
else
msg = "<li>操作失败!"
call message("500")
MyConn.RollbackTrans
end if
end if
'=======================================数据处理结束=================================
'======***页面初始化(表单提交前)***======
else
session("redo") = 0
UserName = ""
call myform()
end if
Response.Write "</body></html>"
MyConn.Close
Set MyConn = Nothing
REM 子过程,定义表单
Sub myform()
Response.Write "<table width=500 border=1 cellspacing=0 cellpadding=5 align=center>"&_
"<form name=form1 method=post onSubmit=submitonce(this)>"&_
"<tr height=30><td rowspan=2 width=100 align=center>姓名</td>"&_
"<td><input type=text name=uname size=40 "&_
"value="""&server.HTMLEncode(username)&"""></td>"&_
"<tr height=30><td>至多5个汉字或10个英文字符</td></tr>"&_
"<tr height=30><td colspan=2 align=center>"&_
"<input type=submit name=Submit value=提交></td></tr>"&_
"</form></table>"
end Sub
%>
以下是myfunction.asp的代码:
<%
'****************************************************************************************
'* NAME:myfunction.asp *
'* CODE:WWW.NETOP.CC *
'* USE:数据验证完整示例--通用函数 *
'* TIME:2005.7 *
'****************************************************************************************
Rem 返回字符串的字节数
function strLength(str)
ON ERROR RESUME NEXT
DIM WINNT_CHINESE
WINNT_CHINESE = (len("中国")=2)
if WINNT_CHINESE then
dim l,t,c
dim i
l=len(str)
t=l
for i=1 to l
c=asc(mid(str,i,1))
if c<0 then c=c+65536
if c>255 then
t=t+1
end if
next
strLength=t
else
strLength=len(str)
end if
if err.number<>0 then err.clear
end function
Rem 判断数据来源
function ChkPost()
dim server_v1,server_v2
chkpost=false
server_v1=Cstr(Request.ServerVariables("HTTP_REFERER"))
server_v2=Cstr(Request.ServerVariables("SERVER_NAME"))
if mid(server_v1,8,len(server_v2))<>server_v2 then
chkpost=false
else
chkpost=true
end if
end function
Rem 转换SQL非法字符
function SQLEncode(fString)
if isnull(fString) then
SQLEncode = ""
exit function
end if
SQLEncode=replace(fString,"'","''")
end function
Rem 提示信息
sub message(w)
Response.Write "<table width="&w&" border=1 cellspacing=0 cellpadding=5 align=center>"&_
"<tr height=30><td>提示信息</td></tr>"&_
"<tr valign=top><td style=""color:red;"">"&msg&"</td></tr></table>"
end sub
%>
<script language="javascript">
//提交按钮只允许按下一次
function submitonce(theform){
if (document.all||document.getElementById){
for (i=0;i<theform.length;i++){
var tempobj=theform.elements[i]
if(tempobj.type.toLowerCase()=="submit"||tempobj.type.toLowerCase()=="reset")
tempobj.disabled=true
}
}
}
</script>
以上通过一个示例展示了对表单提交的数据进行验证的完整过程。具体的验证方法在有关数据验证的前面三篇文章中已做过说明。我想再强调一下myform()中的value="""&server.HTMLEncode(username)&""",请注意双引号及server.HTMLEncode()方法的使用。
也许你注意到了,代码中没有将HTML代码与VBS代码混合,没有使用<%@ Language=VBScript %>,以及在Response.Write中使用了“&_”来连接字串,这样做都有助于提交效率。
[本文仅发表于www.netop.cc,blog.csdn.net/netops,netops.blogchina.com 若见于其它各处,皆为转载]