`
szlxh002
  • 浏览: 34494 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

避免重复提交表单

 
阅读更多

重复提交表单原因:

1.前台多次按了“提交”接钮;

通过在前台按钮的onclick事件来避免

 <script language="javascript">
            <!--
                var checkSubmitFlg=true; 
                function checkSubmit()
                {
                    if(true==checkSubmitFlg)
                    {
                        document.theForm.submit();
                        checkSubmitFlg=false;
                    }
                    else
                    {
                        alert("你已经提交了表单,请不要重复提交!");
                    }
                }
            //-->
        </script>

 

 

 

2.在浏览器按“刷新”按钮

在相关的页面的表单上增加TokenProcessor隐藏域(input type="hidden")。

(1)在后台建立TokenProcessor类

package com.cjg.servlet;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * TokenProcessor类是一个单例类。
*/
public class TokenProcessor
{
    static final String TOKEN_KEY="org.sunxin.token";
   
    private static TokenProcessor instance = new TokenProcessor();

    /**
     * getInstance()方法得到单例类的实例。
     */
    public static TokenProcessor getInstance()
    {
        return instance;
    }

    /**
     * 最近一次生成令牌值的时间戳。
     */
    private long previous;

    /**
     * 判断请求参数中的令牌值是否有效。
     */
    public synchronized boolean isTokenValid(HttpServletRequest request)
    {
        //得到请求的当前Session对象。
        HttpSession session = request.getSession(false);
        if (session == null)
        {
            return false;
        }
        
        //从Session中取出保存的令牌值。
        String saved = (String) session.getAttribute(TOKEN_KEY);
        if (saved == null) {
            return false;
        }
        
        //清除Session中的令牌值。
        resetToken(request);
        
        
        //得到请求参数中的令牌值。
        String token = request.getParameter(TOKEN_KEY);
        if (token == null) {
            return false;
        }
        
        return saved.equals(token);
    }

    /**
     * 清除Session中的令牌值。
     */
    public synchronized void resetToken(HttpServletRequest request)
    {

        HttpSession session = request.getSession(false);
        if (session == null) {
            return;
        }
        session.removeAttribute(TOKEN_KEY);
    }

    /**
     * 产生一个新的令牌值,保存到Session中,
     * 如果当前Session不存在,则创建一个新的Session。
     */
    public synchronized void saveToken(HttpServletRequest request)
    {

        HttpSession session = request.getSession();
        String token = generateToken(request);
        if (token != null) {
            session.setAttribute(TOKEN_KEY, token);
        }

    }

    /**
     * 根据用户会话ID和当前的系统时间生成一个唯一的令牌。
     */
    public synchronized String generateToken(HttpServletRequest request)
    {

        HttpSession session = request.getSession();
        try
        {
            byte id[] = session.getId().getBytes();
            long current = System.currentTimeMillis();
            if (current == previous)
            {
                current++;
            }
            previous = current;
            byte now[] = new Long(current).toString().getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(id);
            md.update(now);
            return toHex(md.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            return null;
        }
    }

    /**
     * 将一个字节数组转换为一个十六进制数字的字符串。
     */
    private String toHex(byte buffer[])
    {
        StringBuffer sb = new StringBuffer(buffer.length * 2);
        for (int i = 0; i < buffer.length; i++)
        {
            sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
            sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
        }
        return sb.toString();
    }
    
    /**
     * 从Session中得到令牌值,如果Session中没有保存令牌值,则生成一个新的令牌值。
     */
    public synchronized String getToken(HttpServletRequest request)
    {
        HttpSession session = request.getSession(false);
        if(null==session)
            return null;
        String token=(String)session.getAttribute(TOKEN_KEY);
        if(null==token)
        {
           token = generateToken(request);
            if (token != null)
            {
                session.setAttribute(TOKEN_KEY, token);
                return token;
            }
            else
                return null;
        }
        else
            return token;
    }
}

 (2)在表单加入TokenProcessor隐藏域

 <body>
        <%
            TokenProcessor processor=TokenProcessor.getInstance(); 
			String token=processor.getToken(request);
        %>
        <form method="post" action="handler" name="theForm">
            <table>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name="username"></td>
                </tr>
                <tr>
                    <td>密码:</td>
    	            <td>
    	                <input type="password" name="password">
                        <input type="hidden" name="org.sunxin.token" value="<%=token%>"/>
    	            </td>
    	        </tr>
    	        <tr>
    	            <td><input type="reset" value="重填"></td>
    	            <td><input type="button" name="btnSubmit" value="提交" onClick="checkSubmit();"/></td>
    	        </tr>
	        </table>
	        
        </form>
    </body>

 (3)处理form的Servlet

 

package com.cjg.servlet;

import javax.servlet.*;
import java.io.*;
import javax.servlet.http.*;
import java.util.*;

import com.cjg.servlet.TokenProcessor;

public class HandlerServlet extends HttpServlet
{
    int count=0;
    public void doPost(HttpServletRequest req, HttpServletResponse resp)
               throws ServletException,IOException
    {
        resp.setContentType("text/html;charset=GBK");
        PrintWriter out=resp.getWriter();
        
        TokenProcessor processor=TokenProcessor.getInstance();
        if(processor.isTokenValid(req))
        {
            try
            {
                Thread.sleep(5000);
            }
            catch(InterruptedException e)
            {
                System.out.println(e);
            }
                
            System.out.println("submit : "+count);
            if(count%2==1)
                count=0;
            else
                count++;
            out.println("success");
        }
        else
        {
            processor.saveToken(req);
            out.println("你已经提交了表单,同一表单不能提交两次。");
        }
        out.close();
    }
}

 

 

 

 

分享到:
评论

相关推荐

    防止Layui form表单重复提交的实现方法

    在这个函数内部,返回false可以阻止表单的提交,即阻止表单数据被发送到服务器,从而避免重复提交。 在上述函数中,如果需要在禁止表单默认提交行为的同时,与服务器进行数据交互,则可以使用JavaScript的...

    javascript方式防止表单重复提交

    8. **表单重定向(Redirect after Post)**:这是一种经典的防止重复提交的方法,提交表单后立即重定向到新的URL,这样即使用户再次点击提交,也会被重定向页面拦截。 9. **使用HTML5的formnovalidate属性**:对于...

    springboot2.1+redis+拦截器 防止表单重复提交

    在现代Web应用开发中,防止表单重复提交是一项重要的任务,因为这可能导致数据不一致性和服务器资源浪费。本文将深入探讨如何使用Spring Boot 2.1、Redis和拦截器来实现这一功能。以下是对这个主题的详细解释: ...

    防止表单重复提交(asp.net )

    - 使用异步处理:使用Ajax提交表单,可以避免页面整体刷新,减少重复提交的机会。 - 提供明确的用户反馈:当表单成功提交后,显示清晰的反馈信息,告知用户操作已完成,防止他们因不清楚状态而多次尝试。 综上所...

    [Jsp]防止页面表单重复提交的解决方法

    这样,即使用户刷新页面,也不会重新发送POST请求,而是进行GET请求,从而避免了重复提交。 3. **服务器端令牌验证** 在服务器生成一个唯一的令牌,将其隐藏字段添加到表单中。当表单提交时,服务器会检查令牌是否...

    修改禁止多次重复提交

    在IT行业中,尤其是在Web开发领域,防止用户多次重复提交数据是一项重要的任务,这可以避免数据库出现冗余数据,保持系统稳定。"修改禁止多次重复提交"这个话题涉及到前端交互、后端处理以及数据库操作等多个层面。...

    Struts2解决表单重复提交

    通过这样的设置,当用户在登录成功后刷新页面时,浏览器将会跳转到指定的页面,而不会导致重复提交表单的问题。 综上所述,Struts2框架提供了token机制以及灵活的跳转方式配置来解决表单重复提交的问题。开发者在...

    spring boot 防止重复提交实现方法详解

    Spring Boot 防止重复提交是指在用户提交表单或请求时,防止同一客户端在短时间内对同一 URL 的重复提交,从而避免服务器端的处理压力和数据的一致性问题。下面将详细介绍 Spring Boot 防止重复提交实现方法的相关...

    表单重复提交问题1

    这种方式可以防止浏览器重定向,避免了F5刷新导致的重复提交。但是,如果用户手动刷新页面,仍有可能引发问题。 2. 使用`Response.sendRedirect()`方法: `resp.sendRedirect(req.getContextPath() + "/manager/...

    Struts之Token解决表单那重复提交

    在处理用户交互时,尤其是表单提交,一个常见的问题是防止表单的重复提交。这可能导致数据的不一致性和其他问题。本文将深入探讨如何在Struts框架中利用Token机制来解决这个问题。 一、表单重复提交问题 表单重复...

    element-ui如何防止重复提交的方法步骤

    在IT行业中,尤其是在前端开发领域,防止用户重复提交是一项重要的任务,这有助于避免因网络延迟或用户误操作导致的数据混乱。Element-UI,一个流行的Vue.js组件库,提供了多种方式来处理这个问题。以下是如何在使用...

    试谈在Web应用中如何避免表单的重复提交.pdf

    如何避免Web应用中的表单重复提交 在Web应用中,避免表单的重复提交是一个棘手的问题。用户在提交表单时可能因为网络速度的原因,或者网页被恶意刷新,导致同一条记录重复插入到数据库中。这篇文章将探讨如何从...

    防止表单重复提交

    然而,如果没有适当处理,可能会出现表单重复提交的问题,这可能导致数据的不一致性和服务器资源的浪费。本篇文章将深入探讨如何防止表单重复提交,主要关注于基于Struts2框架的解决方案。 首先,理解表单重复提交...

    java实现防止表单重复提交

    服务器端避免表单的重复提交,利用同步令牌来解决重复提交的基本原理如下:(1)用户访问提交数据的页面,服务器端在这次会话中,创建一个session对象,并产生一个令牌值,将这个令牌值作为隐藏输入域的值,随表单一起发送到...

    ASP.NET中防止刷新页面造成表单重复提交

    这种方式可以有效地避免重复提交,但对于需要保留用户输入数据的场景不太适用。 除此之外,本文介绍了一种更加灵活且用户体验更好的方法——利用隐藏字段(Hidden Field)配合会话状态(Session State)来判断当前...

    asp.net 页面防止重复提交

    在ASP.NET开发中,页面重复提交是一个常见的问题,它可能导致数据冗余或一致性错误。防止重复提交对于确保数据的准确性和应用的稳定性至关重要。本文将深入探讨如何在ASP.NET环境中解决这个问题。 首先,理解问题的...

    SSH笔记-数据验证、上传下载、避免表单重复提交、自定义拦截器

    接着,我们讨论如何避免表单重复提交。在Web应用中,用户可能无意或有意地多次点击提交按钮,导致数据库中出现重复数据。为了防止这种情况,通常会在服务器端或客户端采取措施。在Struts2中,可以使用Session来存储...

    struts token机制解决表单重复提交

    - **安全性**:避免了重复提交可能导致的系统数据不一致。 - **用户体验**:相比其他如锁定表单的方法,Token机制对用户无感知,不会阻塞用户操作。 - **可扩展性**:可以轻松集成到现有的Struts应用中,无需大规模...

Global site tag (gtag.js) - Google Analytics