防止刷新提交

第一种解决方法,参照老紫竹的思路: 

         可以使用的方法有,在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); 

Struts2.0中防止重复提交

如何在生成页面的时候生成token字段? 
使用token标签。 
代码如下: 
<s:url id="formUrl" action="longLivedTokenAction"/> 
<s:form action="%{formUrl}" method="post"> 
      <s:token /> 
      <s:textfield name="name" label="Name"/> 
      <s:textfield name="password" label="Password"/> 
      <s:submit/> 
      
</s:form> 
其中<s:token />标签用来生成一个唯一的隐藏字段,在运行的时候生成的内容如下: 
<input type="hidden" name="struts.token" value="C21ZWHEH0Q4B6FY15ZO5BFM1I9W8SIQH" /> 

如何在服务器上记录已经提交的token? 
可以使用token intercepter。 
代码如下: 
<action name="longLivedTokenAction" class="com.jpleasure.LongLivedTokenAction"> 
            <interceptor-ref name="token"/> 
            <interceptor-ref name="basicStack"/> 
            <result>/jsp/longLived.jsp</result> 
            <result name="invalid.token">/jsp/invalidToken.jsp</result> 
</action> 
上述<interceptor-ref name="token"/>表示所有的请求必须经过token Interceptortoken Interceptor作用就是纪录所有已经提交的token。那么发现提交的token被重复提交的时候怎么办呢?也许大家已经猜到了,他会重定向到invalid.token所指向的页面,也就是/jsp/invalidToken.jsp。 

基于Interceptor的执行顺序按照struts.xml中定义的顺序,为了更早的结束重复提交的处理,应该将Token Interceptor放在所有Interceptor的最面。 

有了上述的Token Interceptor,可以防止客户重复提交,大大地降低了服务器的负荷。但是对用户来说,可能会很不方便,一不小心点击了提交按钮,进入到了invalid.token页面,就再也回不去了,上述的操作就再也看不见了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值