很多的web应用程序中我们必须要对表单的重复提交做出处理。我们可以使用以下几种方式来防止用户重复提交。
1、使用JavaScript
2、使用Token(令牌)验证提交信息
3、使用session记录上次提交时间
1. 使用JavaScript
有这样的一种情况,用户提交请求之后,页面还没有来得及刷新,或者响应的事件比较长,
那么用户就有可能再次点击提交按钮提交请求。我们可以在页面中定义一个全局的javaScript变量,
存储true和false,true表示已经提交,false表示没有提交,当用户点击了提交之后,首先检查变量的值,
如果为true,则提示用户表单已经提交,如果是false,则将表单提交,然后将变量的值变为true。
这样用户再次点击提交,变量就成true了,此时就提醒用户表单已经提交。还有一种方式就是如果
表单已经提交,则通过javaScript把表单的按钮禁用。将按钮标记的disabled值设置为”disabled”,
这样用户就不能点击按钮提交了。这两种方法由于都是在客户端做出的限制,所以不是很安全,
恶意用户可以通过禁用javaScript代码。还有如果用户使用的不是按钮,
而是通过链接来提交数据的,这种方式就防止不了了。
2、使用Token验证的方式
思路:在程序生成带表的单页面之前,先在服务端生成一个唯一的Token,(一个唯一的字符串)然后放到session中,
生成页面的时候,从session中取出这个标识号,放到隐藏域中,或者附加到url后面,
将来提交的时候将这个标识号一起提交。服务器收到这个提交的数据之后与session中存放的数据对比,
如果一致,则处理请求,然后清除掉session中存放的值(废弃Token).如果不一致,提示重复提交。
我们可以使用UUID作为生成的唯一的Token的值,UUID就是(Universally Unique Identifier,通用唯一识别码)。
JDK中提供了java.util.UUID类可以生成这种码值,只需要调用UUID.randomUUID() 即可。
3、防止用户频繁发出请求
如果用户频繁发出请求,那么就会给服务器造成很大的压力。思路:我们可以在session中记录用户上次请求的时间,
每次请求的时候从session中取出上次请求的时间(时间可以使用System.currenttimeMillis()来获取系统当前时间)
与当前时间进行对比,如果间隔时间太短,则提示给用户。下面给个Struts2框架使用标签防止表单重复提交。
Struts框架就使用了Token的方式来防止表单重复提交。首先需要搭建好Struts2框架所需环境,
<s:token />标签防止重复提交,用法如下:第一步:在表单中加入<s:token />
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Index</title>
</head>
<body>
<s:form action="jason" namespace="/test" method="post">
Name:<s:textfield name="name"/><s:token/>
<input type="submit" value"Submit">
</s:form>
</body>
</html>
第二步:加入了“token”拦截器和“invalid.token”返回结果。因为“token”拦截器在会话的token与请求的token 不一致时,
将会直接返回“invalid.token”结果。服务器端的token是每次请求都会变化,而客户端token是不变的。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd" >
<struts>
<!-- 开发模式-->
<constant name="struts.devMode" value="true"/>
<constant name="struts.ui.theme" value="simple"/>
<package name="com.jason" namespace="/test" extends="struts-default">
<action name="jason" class="com.jason.web.action.BuyerAction">
<!-- struts拦截器-->
<interceptor-ref name="defaultStack"/>
<!-- token拦截器-->
<interceptor-ref name="token"/>
<!-- 配置二次请求后跳转的页面-->
<result name="invalid.token">/index.jsp</result>
<result>/WEB-INF/page/message.jsp</result>
</action>
</package>
</struts>
BuyerAction.java
package com.jason.web.action;
public class BuyerAction {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String execute() throws Exception{
return "success";
}
}
message.jsp页面里显示出时间,如果不适用token当我们每次刷新页面,都会访问Action中的方法,时间在变化。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Index</title>
</head>
<body>
<s:property value="name"/><br/>
<%=new Date() %>
</body>
</html>
当我们第一次请求后,再次请求页面会返回到index.jsp首页。