`

Servlet 防止刷新重复提交

    博客分类:
  • java
 
阅读更多

在java web工程中,当jsp向Servlet提交请求时,如何防止刷新提交(F5)?

         第一种解决方法:

         可以使用的方法有,在jsp中定义一个变量值,这个变量值应该是唯一的,可以使用算法来保证生成数据的唯一性,例如hash算法,或者生成一个随机数 (Random),并将这个数值保存到一个Set中,并将Set保存在session中,提交Servlet时将这个参数传递过去,在Servlet中的 处理:接到参数和session中的set后,判断set中有没有传来的参数值,如果没有则页面是刷新造成的,并不是来自页面的提交,这时不做 insert data的处理。

         jsp 代码

        

<%
        //生成一个formhash,算法可以自己定,不随便重复就可以了
        Random ran = new Random();
        String formhash = String.valueOf(ran.nextInt());
        //读取当前session里面的hashCode集合,此处使用了Set,方便判断。
        Set<String> formhashSession = (Set<String>) session.getAttribute("formhashSession");
        if (formhashSession == null) {
             formhashSession = new HashSet<String>();
        }
        // 检测重复问题
        while (formhashSession.contains(formhash)) {
             formhash = String.valueOf(ran.nextInt());
        }
        // 保存到session里面
        formhashSession.add(formhash);
        // 保存
        session.setAttribute("formhashSession", formhashSession);
     %>

    <form>中增加:<input type="hidden" name="formhash" id="formhash" value="<%=formhash%>" /> 
 

  

         Servlet代码:

        

// 拿到表单的formhash
         String formhash = request.getParameter("formhash");
         // 拿到session里面的集合
         Set<String> formhashSession = (Set<String>) session.getAttribute("formhashSession");
          // 如果没有,则是重复提交,或者非法提交
          if (formhashSession == null || !formhashSession.contains(formhash)) {
                System.out.println("重复提交!");
           }else{

                 //正常的操作

           }

           // 最后,如果操作成功,从session里面把这个formhash 删掉!
           formhashSession.remove(formhash);
           session.setAttribute("formhashSession", formhashSession); 
 

 

          第二种解决方法, 参考struts的token(令牌)机制:

          在提交的时候在Servlet中根据用户的sessionid和当前时间的long值生成一个令牌(每次提交都会生成一个新令牌),将令牌保存在该用户的 会话中,并将令牌的值以request属性形式传到前端页面,在前端页面的form中增加传递令牌的隐藏域<input type="hidden" name="clientToken" value="<%=clientToken%>" />,提交form的时候,也会将clientToken传入Servlet,如果session中保存的令牌值与传入的不同,则是重复提交,因为 每次请求Servlet都会生成新的令牌,刷新时的令牌值是旧的令牌值,不是最新的令牌值。

           jsp代码:

          

<%
    String clientToken = (String)request.getAttribute("clientToken");
    clientToken = clientToken==null?"":clientToken;
           %>

<form>中增加<input type="hidden" name="clientToken" value="<%=clientToken%>" /> 
 

 

          Servlet代码:

         

String clientToken = request.getParameter("clientToken");
          String sessionToken = (String) session.getAttribute("token");

          if(sessionToken!=null&&!clientToken.equals(sessionToken)){
                 System.out.println("请不要重复提交!");
          }else{

                  //正常的操作

          }

           //生成新令牌
           String token = generateToken(request);
           request.setAttribute("clientToken", token);
           //替换旧令牌            session.setAttribute("token", token);

 

public static 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 String.valueOf(md.digest());
		} catch (IllegalStateException e) {
			return (null);
		} catch (NoSuchAlgorithmException e) {
			return (null);
		}
	}
 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics