后台防止表单重复提交

方案一:利用Session防止表单重复提交

具体的做法:
  1、获取用户填写用户名和密码的页面时向后台发送一次请求,这时后台会生成唯一的随机标识号,专业术语称为Token(令牌)。

  2、将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端。

  3、服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。

看具体的范例:

  1.创建FormServlet,用于生成Token(令牌)和跳转到form.jsp页面

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

  public class FormServlet extends HttpServlet {
    private static final long serialVersionUID = -884689940866074733L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {

        String token =  UUID.randomUUID().toString() ;//创建令牌
        System.out.println("在FormServlet中生成的token:"+token);
         request.getSession().setAttribute("token", token);  //在服务器使用session保存token(令牌)
         request.getRequestDispatcher("/form.jsp").forward(request, response);//跳转到form.jsp页面
     }

     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }

}

  2.在form.jsp中使用隐藏域来存储Token(令牌)

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  <html>
  <head>
  <title>form表单</title>
  </head>

  <body>
      <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" method="post">
         <%--使用隐藏域存储生成的token--%>
         <%--
             <input type="hidden" name="token" value="<%=session.getAttribute("token") %>">
         --%>
         <%--使用EL表达式取出存储在session中的token--%>
         <input type="hidden" name="token" value="${token}"/>
         用户名:<input type="text" name="username">
         <input type="submit" value="提交">
     </form>
 </body>
 </html>

  3.DoFormServlet处理表单提交 

import java.io.IOException;
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;

  public class DoFormServlet extends HttpServlet {

     public void doGet(HttpServletRequest request, HttpServletResponse response)
                 throws ServletException, IOException {

             boolean b = isRepeatSubmit(request);//判断用户是否是重复提交
             if(b==true){
                 System.out.println("请不要重复提交");
                 return;
             }
             request.getSession().removeAttribute("token");//移除session中的token
             System.out.println("处理用户提交请求!!");
         }

         /**
          * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
          * @param request
          * @return
          *         true 用户重复提交了表单
          *         false 用户没有重复提交表单
          */
         private boolean isRepeatSubmit(HttpServletRequest request) {
             String client_token = request.getParameter("token");
             //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
             if(client_token==null){
                 return true;
             }
             //取出存储在Session中的token
             String server_token = (String) request.getSession().getAttribute("token");
             //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
             if(server_token==null){
                return true;
             }
             //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
             if(!client_token.equals(server_token)){
                 return true;
             }

             return false;
         }

     public void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         doGet(request, response);
     }

 }

方案二:判断请求url和数据是否和上一次相同

  推荐,非常简单,页面不需要任何传入,只需要在验证的controller方法上写上自定义注解即可

  写好自定义注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;  

/**
 * 一个用户 相同url 同时提交 相同数据 验证
 * @author Administrator
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SameUrlData {  

}  

  写好拦截器

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;  

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;  

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;  

import com.thinkgem.jeesite.common.mapper.JsonMapper;  

/**
 * 一个用户 相同url 同时提交 相同数据 验证
 * 主要通过 session中保存到的url 和 请求参数。如果和上次相同,则是重复提交表单
 * @author Administrator
 *
 */
public class SameUrlDataInterceptor  extends HandlerInterceptorAdapter{  

      @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                Method method = handlerMethod.getMethod();
                SameUrlData annotation = method.getAnnotation(SameUrlData.class);
                if (annotation != null) {
                    if(repeatDataValidator(request))//如果重复相同数据
                        return false;
                    else
                        return true;
                }
                return true;
            } else {
                return super.preHandle(request, response, handler);
            }
        }
    /**
     * 验证同一个url数据是否相同提交  ,相同返回true
     * @param httpServletRequest
     * @return
     */
    public boolean repeatDataValidator(HttpServletRequest httpServletRequest)
    {
        String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap());
        String url=httpServletRequest.getRequestURI();
        Map<String,String> map=new HashMap<String,String>();
        map.put(url, params);
        String nowUrlParams=map.toString();//  

        Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData");
        if(preUrlParams==null)//如果上一个数据为null,表示还没有访问页面
        {
            httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);
            return false;
        }
        else//否则,已经访问过页面
        {
            if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+数据和本次url+数据相同,则表示城府添加数据
            {  

                return true;
            }
            else//如果上次 url+数据 和本次url加数据不同,则不是重复提交
            {
                httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);
                return false;
            }  

        }
    }  

}  
<mvc:interceptor>
     <mvc:mapping path="/**"/>
     <bean class="*.*.SameUrlDataInterceptor"/>
</mvc:interceptor>

原文地址:https://www.cnblogs.com/myseries/p/10802079.html

时间: 2024-08-25 06:59:41

后台防止表单重复提交的相关文章

表单重复提交问题

一.常见的重复提交问题  a>点击提交按钮两次.  b>点击刷新按钮.  c>使用浏览器后退按钮重复之前的操作,导致重复提交表单.  d>使用浏览器历史记录重复提交表单.  e>浏览器重复的HTTP请求. 二.防止表单重复提交原理 提交表单的时候提交一份随机的字符串或随机数字等等,再把这个随机的数据存到request里面,然后把表单数据提交,在后台验证的时候判断提交的这两份额外的数据是否一致,如果一致,则把其中一份删除掉,这么做的目的是防止再次提交,继续进行操作,如果不一致,

js阻止form表单重复提交

防止表单重复提交的方法总体来说有两种,一种是在js中阻止重复提交:另一种是在后台利用token令牌实现,大致思路是生成一个随机码放到session和form表单的隐藏输入框中,提交表单时两者对比,表单处理完毕清空或者修改session中的token. 在js中处理简单易懂,同时能解决我现在所做的项目中的问题,目前暂用js处理,后期如有需要再研究token机制.代码如下: 1.表单提交后禁用提交按钮(在本项目中表单提交完成后,如果处理成功都把form表单关掉了) 1 /** 2 * form表单格

php通过token验证表单重复提交

PHP防止重复提交表单 2016-11-08 轻松学PHP 我们提交表单的时候,不能忽视的一个限制是防止用户重复提交表单,因为有可能用户连续点击了提交按钮或者是攻击者恶意提交数据,那么我们在提交数据后的处理如修改或添加数据到数据库时就会惹上麻烦. 那么如何规避这中重复提交表单的现象出现呢?我们可以从很多方面入手,首先从前端做限制.前端JavaScript在按钮被点击一次后禁用,即disabled,这个方法简单的防止了多次点击提交按钮,但是缺点是如果用户禁用了javascript脚本则失效.第二,

struts2防止表单重复提交的解决方案

一.造成重复提交主要的两个原因:    在平时的开发过程中,经常可以遇到表单重复提交的问题,如做一个注册页面,如果表单重复提交,那么一个用户就会注册多次,重复提交主要由于两种原因. 1. 一是,服务器处理时间久.当用户在表单中填完信息,点击“提交”按钮后,由于服务器反应时间过长没能及时看到响应信息,或者出于其它目的,再次点击“提 交”按钮,从而导致在服务器端接收到两条或多条相同的信息.如果信息需要存储到后台数据库中,如此以来就会产生数据库操作异常提示信息,以至于给用户带来 错误信息提示,从而给用

Django框架开发中避免表单重复提交

Form表单做为web2.0时代的重要角色,也是我们与web网站进行数据交互的重要渠道,但是大家在web网站开发过程中,都会遇到一个问题,那就是如何避免表单重复提交,我们可不确定用户可在提交了一个表单后,是否有足够的耐心等待我们的程序加载完成,如果此时用户不耐烦的在前台重复刷新页面,那么就会造成数据重复提交.信息不准确,因此我们在程序设计时一定要规避这样的问题,接下来介绍一下在Django框架开发中如何避免此问题. 首先说明一下Http协议中两种非常常见的方法GET和POST. 1.GET方法往

【struts2】struts防止表单重复提交

一.概述 表单重复提交已经存在很久了,也有很多讨论.防止表单重复提交主要是防止"服务器处理慢时的页面刷新",以及浏览器后退后再次提交,甚至是点击提交按钮的时候手快点了很多次. 常用的JS将提交按钮设置成disabled,这种防止不了页面刷新,重定向防止不了浏览器后退后重复提交,两者结合也没用. struts2采用的是页面hidden+session来实现防止重复提交,通过拦截器token或或tokenSession来说hi线,其思想很简单,本文主要是讨论实现代码中涉及的细节. 二.原理

Servlet、SPringMVC、Struts等防止表单重复提交的多种处理方法

第一种处理方法(非拦截器): 目前这种方法不建议,因为JSP规范不建议写JAVA代码.这种可以方便第二种处理方法的理解,第二种方法引入拦截器的思想,原理基本一样,模仿Struts的Token机制. 1.在需要防止重复的jsp中加入下面的java代码, <%@page import="java.util.Random"%> <%@page import="java.util.Set"%> <%@page import="java

跨域与防止表单重复提交

什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的. 广义的跨域: 1.) 资源跳转: A链接.重定向.表单提交 2.) 资源嵌入: <link>.<script>.<img>.<frame>等dom标签,还有样式中background:url().@font-face()等文件外链 3.) 脚本请求: js发起的ajax请求.dom和js对象的跨域操作等 其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场

HTTP(“跨域问题”和“防止表单重复提交”)

一.跨域问题 能够正常请求,但是没有办法获取到响应结果 解决方案一:设置请求头,在请求的资源中设置Access-Control-Allow-Origin请求头 //3.设置请求头 response.setHeader("Access-Control-Allow-Origin", "*"); 解决方案二:.JSONP解决跨域问题 普通的跨域访问问题,浏览器会进行拦截,凡是src属性的都不会拦截 ajax:http://www.a.com:8080/a/AServlet