`
郑云飞
  • 浏览: 817054 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring MVC 用拦截器+token防止重复提交

阅读更多

最近再开发一个图书管理的项目,在线发布图书的时候,明明只点击了一下,偏偏却保存了多条记录,无奈之下只好加拦截器防止重复提交:

1:首先定义注解:

首先自定义一个注解:

package com.dinfo.interceptor;

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

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

    boolean save() default false;

    boolean remove() default false;
}
2:接着实现一个拦截器借口:
package com.dinfo.interceptor;

import java.lang.reflect.Method;
import java.util.UUID;

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

import org.apache.log4j.Logger;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class TokenInterceptor extends HandlerInterceptorAdapter {
    private static final Logger LOG = Logger.getLogger(Token.class);
    @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(true).setAttribute("token", UUID.randomUUID().toString());
                }
                boolean needRemoveSession = annotation.remove();
                if (needRemoveSession) {
                    if (isRepeatSubmit(request)) {
                        LOG.warn("please don't repeat submit,url:"+ request.getServletPath());
                        return false;
                    }
                    request.getSession(true).removeAttribute("token");
                }
            }
            return true;
        } else {
            return super.preHandle(request, response, handler);
        }
    }

    private boolean isRepeatSubmit(HttpServletRequest request) {
        String serverToken = (String) request.getSession(true).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;
    }
}

 3: spring 拦截器配置:

<mvc:interceptors>
        <!-- 配置Token拦截器,防止用户重复提交数据 -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/><!--这个地方时你要拦截得路径 我这个意思是拦截所有得URL-->
            <bean class="com.dinfo.interceptor.TokenInterceptor"/><!--class文件路径改成你自己写得拦截器路径!! -->
        </mvc:interceptor>
</mvc:interceptors>

 4:在跳转页面的方法加上  @Token(save=true)

@RequestMapping(value = "/webui/payPage.html", method = RequestMethod.GET)
	@Token(save=true)
	public ModelAndView gonext(HttpServletRequest request,
							   HttpServletResponse response, ModelMap model, String  id,int number) {
		ModelAndView mv=new ModelAndView();
		FmUtils.FmData(request,model);
		if(!StringUtils.isEmpty(id)) {
			TudouBookInfo bookInfo=bookService.findById(id);
			if(!StringUtils.isEmpty(bookInfo)){
				bookInfo.setNumber(number);
				float price=Float.parseFloat(bookInfo.getPrice());
				float totalPrice=number *price;
				bookInfo.setTotalPrice(totalPrice+"");
				mv.addObject("book",bookInfo);
			}
		}
		mv.setViewName(MobilePageContants.MY_PAY_PAGE);
		mv.addObject("token",id);
		return mv;
	}

 5:在提交的方法上加    @Token(remove=true)

@RequestMapping(value = "/webui/paysave.html", method = RequestMethod.POST)
	@Token(remove=true)
	public ModelAndView paysave(HttpServletRequest request,
								   HttpServletResponse response, ModelMap model, String  id,String number) {
		ModelAndView mv=new ModelAndView();

 

 6:OK,到这里大功告成,你就可以发现已经没有办法重复提交数据了!

 

 

分享到:
评论
3 楼 greatwqs 2018-08-21  
在前置请求页面返回token, 在提交接口中验证token, 并删除.
还是不错的方案.    
2 楼 zhukewen_java 2017-11-25  
这种方法的缺陷在于如果请求了两个save=true的方法,后面的请求的,会把session里的token override掉,比如
1,请求页面a
2,请求页面b
3,提交页面a(这里会失败)
4,   提交页面b
倒是可以在 session中放一个set,请求的时候判断token在不在这个set中(if (set.remove(token))
1 楼 byrgl5 2016-10-21  
请问如果重复提交了三次呢?能避免吗?

相关推荐

    Spring注解方式防止重复提交原理详解

    Spring 注解方式防止重复提交原理是通过使用注解和拦截器来实现防止重复提交的。该方法可以防止用户重复提交表单,以提高系统的安全性和可靠性。 2. 使用 Token 防止重复提交 使用 Token 防止重复提交是一种常用...

    Spring mvc防止数据重复提交的方法

    Spring MVC 防止数据重复提交的方法是使用 Token 机制来实现的,该机制通过在服务器端生成一个随机的 UUID,并将其存储在 Session 中,然后在客户端提交数据时带上该 UUID,服务器端在接收到该 UUID 后,对其进行...

    Spring MVC接口防数据篡改和重复提交

    Spring MVC接口防数据篡改和重复提交 Spring MVC框架中,数据篡改和...本文详细介绍了如何使用Spring MVC防止数据篡改和重复提交,包括自定义注解和拦截器的实现。通过使用这些技术,可以确保数据的安全性和完整性。

    springmvc(spring4版本)+自带登录和拦截器

    本项目是一个基于Spring 4的Spring MVC实现,内含登录功能和拦截器,可以直接运行,为开发者提供了一个快速开发的基础模板。 首先,让我们详细了解一下Spring MVC的核心概念: 1. **DispatcherServlet**:它是...

    springMVC自定义防重复提交

    本篇将详细介绍如何在Spring MVC中自定义实现防重复提交机制,特别是通过使用“token”标签的方式。 首先,理解防重复提交的核心原理:在客户端请求时生成一个唯一的标识(token),并将这个标识存储在服务器端和...

    springMVC中基于token防止表单重复提交方法

    SpringMVC中基于Token防止表单重复提交方法是指通过在SpringMVC配置文件中添加拦截器配置,来拦截页面请求和表单提交请求,以防止表单重复提交。下面是该方法的实现思路和实现方式: 实现思路: 1. 在SpringMVC...

    Servlet、Struts、SpringMVC对于表单重复提交的解决方案

    3. **Spring的拦截器(Interceptor)**:可以自定义拦截器,实现`HandlerInterceptor`接口,其中的`postHandle()`方法可以用来处理表单提交后的状态,防止重复提交。 4. **令牌(Token)机制**:与Servlet中的令牌...

    利用struts的token控制重复提交

    1. **配置Action**: 在Struts配置文件(如struts.xml)中,为需要防止重复提交的Action添加`token`拦截器。 ```xml &lt;interceptor-ref name="token"/&gt; &lt;result name="success"&gt;/success.jsp ...

    spring boot 拦截器拦截/Filter 过滤session案例

    在本文中,我们将深入探讨如何在Spring Boot应用中使用拦截器(Interceptor)和过滤器(Filter)来处理用户的登录session。这两个组件都是Spring框架的重要部分,它们在处理HTTP请求和响应时发挥着关键作用。 首先...

    Springmvc登录拦截器Demo

    本文将深入探讨如何使用Spring MVC的拦截器实现登录验证,并提供相关知识点。 1. **Spring MVC 拦截器简介** Spring MVC的拦截器是基于Servlet的Filter的一种扩展,它允许开发者在请求被控制器处理之前或之后执行...

    CXF3.1.16 +Spring4 +MyBatis + Maven自定义拦截器 WebService实例源码下载

    "CXF3.1.16 +Spring4 +MyBatis + Maven自定义拦截器 WebService实例源码下载" 这个标题揭示了该项目的核心技术栈,包括: 1. CXF 3.1.16:这是一个开源的服务框架,用于构建和开发服务,支持SOAP和RESTful Web服务...

    Spring+SpringMVC+MyBatis+SpringBoot视频05

    视频内容可能涵盖了如何创建 Spring Boot 应用中的拦截器(Interceptor),用于处理如登录验证这样的安全问题。拦截器可以在请求被控制器处理之前或之后执行逻辑,比如检查用户是否已登录,确保只有授权的用户才能...

    spring mvc login demo

    - `springmvc-servlet.xml`:配置Spring MVC的相关组件,如视图解析器、拦截器等。 - `applicationContext.xml`:配置Spring的核心组件,如Bean的定义和数据源。 ### 9. 测试与调试 使用Postman或类似工具模拟POST...

    毕业设计管理系统java服务端,采用spring mvc.zip

    Spring MVC的核心组件包括DispatcherServlet、Controller、Model、View以及一系列的拦截器(Interceptor)。 1. DispatcherServlet:作为前端控制器,它是整个Spring MVC流程的起点,负责接收HTTP请求,并根据请求...

    spring-token:整合JWT,spring,springMVC,实现基于token验证

    因为这篇博客讲的是基于JWT和spring,springMVC的整合,所以如果有小伙伴想整合JWT和spring-boot,只需要将spring基于xml文件的拦截器配置方式转换成 spring-boot的配置方式就ok了。 欢迎大家讨论,分享!

    拦截器和控制器的区别

    4、拦截器可以利用依赖注入,因此在spring框架程序中,优先拦截器 5、拦截器是包裹在过滤器中使用的。 复习 converter 转换器 i18n struts2 spring MVC 拦截器 interceptor 过滤器 filter web.xml ...

    java拦截器

    | Token | 通过Token防止重复提交 | | Validation | 使用定义的规则验证提交的数据 | | Workflow | 调用Action的validate方法,如果验证失败则返回输入视图 | #### 四、拦截器的作用与优势 拦截器在软件开发中...

    spring boot MVC

    在"spring boot 携带token登录,token拦截器,增删改查功能"这个描述中,我们可以深入探讨几个关键知识点。 1. **JWT(JSON Web Tokens)登录**: JSON Web Tokens (JWT) 是一种轻量级的身份验证机制,用于在...

    spring+springmvc+Interceptor+jwt+redis实现sso单点登录

    ### 使用Spring + SpringMVC + Interceptor + JWT + Redis 实现SSO单点登录 #### 一、背景介绍 在当前互联网技术飞速发展的背景下,越来越多的企业选择采用微服务架构来构建自己的应用系统。分布式环境下,如何...

Global site tag (gtag.js) - Google Analytics