在客户端限制表单重复提交有两种方法:
第一种:在javascript脚本中设置一个标志变量,来区分表单是否已经提交。如果已经提交,则弹出对话框告诉用户“重复提交”。
第二种:在单击提交按钮以后将提交按钮设置为disabled状态,这样用户就无法再提交按钮,客户端也就无法重复提交。
采用第一种方法:
1.新建一个ClientTest1.jsp文件,代码如下:
<%@ page language="java" contentType="text/html; charset=Gb2312"
pageEncoding="GB2312"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Gb2312">
<title>客户端限制重复提交</title>
<script language="javascript"
<!--定义重复提交标志变量 -->
var repeatSubmitFlag = false;
<!-- 重复提交检查函数 -->
function checkSubmit()
{
if(repeatSubmitFlag) <!-- 如果标志为true,则说明页面已经提交 -->
{
window.alert('禁止重复提交!');
return false;
}
else
{
repeatSubmitFlag = true;
return true;
}
}
</script>
</head>
<body bcolor="#ffffff">
<form name="form_client" action="http://www.dlmu.edu.cn" onsubmit="return checkSubmit();">
<input type="checkbox" name="check_1" checked=true/>大连海事大学
<input type="submit" name="submitok"/>
</form>
</body>
</html>
2.如果重复提交表单就会弹出错误提示对话框
采用第二种方法:
1.新建一个ClientTest2.jsp文件,代码如下:
<%@ page language="java" contentType="text/html; charset=GB2312"
pageEncoding="Gb2312"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Gb2312">
<title>客户端限制重复提交-2</title>
</head>
<body bgcolor="#ffffff">
<form name="form_client" action="http://www.dlmu.edu.cn"
onsubmit="window.document.form_client.submitok.disabled=true; return true;">
<input type="checkbox" name="check_1" checked="true"/>大连海事大学
<input type="submit" name="submitok"/>
</form>
</body>
</html>
2.如果重复提交表单就会弹出错误提示对话框
3 利用struts的同步令牌机制
利用同步令牌(Token)机制来解决Web应用中重复提交的问题,Struts也给出了一个参考实现。
基本原理:
服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。
if (isTokenValid(request, true)) {
// your code here
return mapping.findForward("success");
} else {
saveToken(request);
return mapping.findForward("submitagain");
}
Struts根据用户会话ID和当前系统时间来生成一个唯一(对于每个会话)令牌的,具体实现可以参考TokenProcessor类中的generateToken()方法。
1. //验证事务控制令牌,<html:form >会自动根据session中标识生成一个隐含input代表令牌,防止两次提交
2. 在action中:
//<input type="hidden" name="org.apache.struts.taglib.html.TOKEN"
// value="6aa35341f25184fd996c4c918255c3ae">
if (!isTokenValid(request))
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.transaction.token"));
resetToken(request); //删除session中的令牌
3. action有这样的一个方法生成令牌
protected String generateToken(HttpServletRequest request) {
HttpSession session = request.getSession();
try {
byte id[] = session.getId().getBytes();
byte now[] =
new Long(System.currentTimeMillis()).toString().getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(id);
md.update(now);
return (toHex(md.digest()));
} catch (IllegalStateException e) {
return (null);
} catch (NoSuchAlgorithmException e) {
return (null);
}
}