利用Token解决重复提交:http://www.javawebstudio.com/bbs/dispbbs.asp?boardID=44&ID=216&page=1

解决方案 »

  1.   

    http://macrochen.blogdriver.com/macrochen/334679.html1·使用redirect = "true"
    <action 
     path="/testingOption"   
     name="optionForm" 
     parameter="method" 
     scope="request" 
     type="com.appeon.manager.action.TestingOptionAction" 
     validate="false">
     <forward name="editTesting"    path="/pages/infomanager/superTesting/wap/content/editTesting.jsp" redirect = "true"/>
    </action>
    或者
    在action中return new ActionForward(String path,Boolean redirect) redirect设置为true
    缺点:如果jsp中使用了相对路径,而又没有设置<base href = "xxxx"/>,重定向之后可能一些相对路径会出问题。还有在设置<base href = "xxx"/>的时候,如果你的地址栏中使用的是ip地址,而base的href中使用的服务器名,会导致主机名不一致而导致session中的数据被清掉了。
    2·使用令牌
    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
    struts自带的例子:
    Struts 里面有一个检查重复提交的机制:
    具体可以参看 Struts-example 里面的相关程序:
    in EditRegistrationAction:
    // Set a transactional control token to prevent double posting
    saveToken(request);
    in SaveRegistrationAction 里面:
    if (!isTokenValid(request)) {
        // 处理错误
    }
    resetToken(request);《j2ee核心模式》这本书上有详细介绍。
      基本原理
     第一次提交,生成同步令牌 写入到session,同时把同步令牌写入到返回页中;
     再次提交,比较同步令牌,如果相同,重复上面动作, 不同则重复提交了。
     if (!isTokenValid(request)) {
      errors.add(ActionErrors.GLOBAL_ERROR,
             new ActionError("error.transaction.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")%>>
      

  2.   

    JavaScript解决的话,我原来在ASP上面是利用Cookie来进行的。提交前设置Cookie,提交后把Cookie清除,这时重复提交就没有Cookie而不能提交了。
      

  3.   

    提交后就把提交的按钮disable掉,从而使之不能重复点击