Spring MVC防止数据重复提交(防止二次提交)

SpringMvc使用Token 
使用token的逻辑是,给所有的url加一个拦截器,在拦截器里面用java的UUID生成一个随机的UUID并把这个UUID放到session里面,然后在浏览器做数据提交的时候将此UUID提交到服务器。服务器在接收到此UUID后,检查一下该UUID是否已经被提交,如果已经被提交,则不让逻辑继续执行下去…

首先要定义一个annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Token {

    boolean save() default false;

    boolean remove() default false;
}

定义拦截器TokenInterceptor:

public class TokenInterceptor 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();
            Token annotation = method.getAnnotation(Token.class);
            if (annotation != null) {
                boolean needSaveSession = annotation.save();
                if (needSaveSession) {
                    request.getSession(false).setAttribute("token", UUID.randomUUID().toString());
                }
                boolean needRemoveSession = annotation.remove();
                if (needRemoveSession) {
                    if (isRepeatSubmit(request)) {
                        return false;
                    }
                    request.getSession(false).removeAttribute("token");
                }
            }
            return true;
        } else {
            return super.preHandle(request, response, handler);
        }
    }

    private boolean isRepeatSubmit(HttpServletRequest request) {
        String serverToken = (String) request.getSession(false).getAttribute("token");
        if (serverToken == null) {
            return true;
        }
        String clinetToken = request.getParameter("token");
        if (clinetToken == null) {
            return true;
        }
        if (!serverToken.equals(clinetToken)) {
            return true;
        }
        return false;
    }
}

Spring MVC的配置文件里加入:

<mvc:interceptors>
        <!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 -->
            <bean class="****包名****.TokenInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

用法:

  1. 在新增或者修改前的编辑的controll方法上增加@Token(save=true)
  2. 在表单提交的controller的方法上增加@Token(remove=true)
  3. 在表单中增加<input type="hidden" name="token" value="${token}" />
时间: 2024-08-10 09:35:14

Spring MVC防止数据重复提交(防止二次提交)的相关文章

Spring MVC防止数据重复提交

现实开发中表单重复提交的例子很多,就包括手上这个门户的项目也有这种应用场景,用的次数多,但是总结,这还是第一次. 一.基本原理 使用token,给所有的url加一个拦截器,在拦截器里面用java的UUID生成一个随机的UUID并把这个UUID放到session里面,然后在浏览器做数据提交的时候将此UUID提交到服务器.服务器在接收到此UUID后,检查一下该UUID是否已经被提交,如果已经被提交,则不让逻辑继续执行下去 二.代码 2.1.注解Token代码: @Target(ElementType

新建 Spring Mvc Web + Maven 的 maven 错误 (二)

新建项目后,可能由于哪边配置不正确,或也可能是编码问题,就有可能在创建初始就可能发生错误: 这是 pom.xml 中提示的错误,有的人说要删除 maven 的本地仓库位置:c:\用户[Users]\Administrator\.m2的文件夹,有的说只要下载的包即要: 这里我们重建本项目构建空间的 maven 仓库位置; Maven配置 当然你本机或服务器,应当要有 maven 的文件包,maven 不必安装,只需要拷贝到适当的位置即可,这里用的 3.0.4版: 修改配置 1. 首先在本地选择或创

【Spring学习笔记-MVC-10】Spring MVC之数据校验

作者:ssslinppp       1.准备 这里我们采用Hibernate-validator来进行验证,Hibernate-validator实现了JSR-303验证框架支持注解风格的验证.首先我们要到http://hibernate.org/validator/下载需要的jar包,这里以4.3.1.Final作为演示,解压后把hibernate-validator-4.3.1.Final.jar.jboss-logging-3.1.0.jar.validation-api-1.0.0.G

Spring MVC : Java模板引擎 Thymeleaf (二)

本文原计划直接介绍Thymeleaf的视图解析,但考虑到学习的方便,决定先构建一个spring-mvc. 下面的所有过程只要一个记事本和JDK就够了. 第一步,使用maven构建一个web app. <span style="font-size:18px;">mvn archetype:generate -DgroupId=org.nwpu.chen -DartifactId=spring-mvc -DarchetypeArtifactId=maven-archetype-

Spring MVC服务器端防止重复提交

实现机制是使用token,简单说下: (a)进入下单页,会生成一个token,同时存在两个地方:session(或redis也可以)和页面 (b)提交时,服务器接收到页面的token后,会和session中的token比较,相同则允许提交,同时删除session中的token; (c)如果重复提交,则session中已经没有token(已被步骤b删除),那么校验不通过,则不会真正提交. 拦截器代码:下载 Java代码 package com.chanjet.gov.filter; import 

Spring MVC 的 研发之路 (二)

二.web.xml的简单配置介绍1 1.启动Web项目时,容器回去读web.xml配置文件里的两个节点<context-param>和<listener> 2.接着容器会创建一个servletContext(上下文)应用范围内都能使用这个上下文 3.接着容器会将读取到<context-param>转化为键值对,并交给ServletContext. 4.通过<listener>创建监听 5.在监听的类中会有一个contextInitialized(Servle

Spring MVC 指导文档解读(二)

Special Bean Types In the WebApplicationContext 解读 1.WebApplicationContext 特有的几种 Bean Types 2. 也表明 与之相对的 还有 ApplicationContext 下面这几种特有的 web bean types 也理应定义到 web 的上下文配置文件中,比如 a-servlet.xml Table 22.1. Special bean types in the WebApplicationContext B

Spring Mvc 前台数据的获取、SpringMvc 表单数据的获取

首先在web.xml 里面配置一个编码过滤器 1 <!-- springmvc框架本身没有处理请求编码,我们自己配置一个请求编码过滤器 --> 2 <filter> 3 <filter-name>encodingFilter</filter-name> 4 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 5 <

spring mvc @Valid 数据验证

//对书的单价校验不能是空,价格在20-100之间   @DecimalMax(value = "100", message = "价格不超过100元")   @DecimalMin(value = "20",message = "价格不低于20元") @Pattern(regexp = "1[345678][0-9]{9}",message = "手机号不符合规格") @IDValid