isTokenValid Return true if there is a transaction token stored in the user's current session, and the value submitted as a request parameter with this action matches it.
resetToken Reset the saved transaction token in the user's session.
saveToken Save a new transaction token in the user's current session, creating a new session if necessary.
为了防止用户重复提交,在数据读入.do未中加入saveToken(request),在第二个.do的开始判断isTokenValid(request)如果有效继续否则丢出错误信息,最后resetToken(requet)注销token
基本原理 第一次提交,生成同步令牌 写入到session,同时把同步令牌写入到返回页中; 再次提交,比较同步令牌,如果相同,重复上面动作, 不同则重复提交了。
if (!isTokenValid(request)) {
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.transaction.token"_));
}
resetToken(request);
Struts中的isTokenValid(request,boolean)是用来防止表单重复提交的! Struts在你每次访问Action的时候,根据用户会话ID和当前系统时间对于每个会话生成一个唯一令牌,保存在你的Session里面,如果你在Action里的函数里面,使用了saveToken(request),那么这个令牌也会保存在这个Action所Forward到的jsp所生成的静态页面里。 如果你在你Action的方法里使用了isTokenValid,那么Struts将会从你的request里面去获取这个令牌值,然后和Session里的令牌值做比较,如果两者相等,就不是重复提交,如果不相等,就是重复提交了。
if (!isTokenValid(request)) { // 判断当前用户会话中的令牌值和请求参数中的令牌值是否匹配。如果不匹配,就生成错误信息,并调用saveToken(request)方法,创建一个新令牌,然后返回。 request.setAttribute("info", "不允许重复提交表单!");
} else { // 如果匹配,就调用resetToken(request)方法,从当前会话中删除Token,然后执行插入数据的操作。 resetToken(request); }
3·客户端将提交按钮设置为disabled
4·引入同步机制(SynId)。
指导思想就是,为每一个页面编号,并在客户端和服务器端各产生一个副本,每次通过比较两端的编号是否一致,达到同步的目的。首先,由服务器产生这个编号,发送到客户端。这样这个编号在服务器和客户端各有一个副本。当客户提交页面时,服务器首先比较两个编号是否一致。如果一致,则处理提交,并产生一个新的编号,返回给客户端。此时如果客户回退并再次提交,客户端是旧编号,服务器端是新编号,显然不一致,因此服务器将判定这是一次重复提交,不予受理。对于同步环的产生、保存、比较,最好生成一个新“同步助手”类SynHelper,完成相应的操作。调用它的Jsp文件只需以JavaBean的形式引用即可。下面描述作为类SynHelper所需的基本方法:
private String generateSynId(){
return Long.toString(System.currentTimeMillis());
}
protected void saveSynId(HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute(SYN_ID,generateSynId());
}
protected boolean compareSynId(HttpServletRequest request){
try{
HttpSession session = request.getSession();
String serverSynId = session.getAttribute(SYN_ID);
String clientSynId = request.getParameter(“CLIENT_SYN_ID”);
Return (serverSynId.equals(clientSynId));
}catch(Exception e){
return false;
}
}
对于客户端jsp在收到服务器的同步环后,必须将其保存在hidden中。具体实现如下:
<input type="hidden" name="CLIENT_SYN_ID" value=<%=session.getAttribute("SYN_ID")%>>