spring MVC 后台token防重复提交解决方案

看到公司有个部门提出了这个问题,补个粗略的解决方案。。。

1.编写拦截器

/**
 * Description: 防止重复提交
 *
 * @Author liam
 * @Create Date: 2018/3/9 9:22
 */
public class AvoidReSubmitIntercepter extends HandlerInterceptorAdapter {

    private static final String SPLIT_FLAG = "_";
    private static final String AVOID_RE_SUBMIT_TOKEN_KEY = "identifier_token";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (checkAvoidReSubmitTokenOn(handler,AvoidReSubmitBehavior.Check)) {
            //验证是否重复
            if (checkIsRepeatSubmit(request)) {
                //重复提交
                return false;
            }
        }
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if (checkAvoidReSubmitTokenOn(handler,AvoidReSubmitBehavior.Create)) {
            Random random = new Random();
            String uuid = UUID.randomUUID().toString().replace(SPLIT_FLAG, String.valueOf(random.nextInt(100000)));
            String tokenValue = String.valueOf(System.currentTimeMillis());
            String transferToken = uuid + SPLIT_FLAG + tokenValue;
            request.setAttribute(AVOID_RE_SUBMIT_TOKEN_KEY, transferToken);
            request.getSession(true).setAttribute(uuid, tokenValue);
        }
        super.postHandle(request, response, handler, modelAndView);
    }

    /**
    * Description: 是否开启防重规则
    *
    * @Author liam
    * @Create Date: 2018/3/9 10:33
    */
    private boolean checkAvoidReSubmitTokenOn(Object handler,AvoidReSubmitBehavior behavior) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method invokeMethod = handlerMethod.getMethod();
        AvoidReSubmitToken avoidReSubmitToken = invokeMethod.getAnnotation(AvoidReSubmitToken.class);
        if (avoidReSubmitToken != null && avoidReSubmitToken.behavior().equals(behavior)) {
            return true;
        }
        return false;

    }

    private boolean checkIsRepeatSubmit(HttpServletRequest request) {
        String clientToken = request.getParameter(AVOID_RE_SUBMIT_TOKEN_KEY);
        if (StringUtils.isEmpty(clientToken)) {
            clientToken = request.getParameter(AVOID_RE_SUBMIT_TOKEN_KEY);
            if (StringUtils.isEmpty(clientToken)) {
                return true;
            }
        }
        String[] clientTokensDetail = StringUtils.split(clientToken, SPLIT_FLAG);
        if (clientTokensDetail.length == 2) {
            String uuid = clientTokensDetail[0];
            String token = clientTokensDetail[1];
            String serverToken = (String) request.getSession(true).getAttribute(uuid);
            if (StringUtils.isNotEmpty(serverToken) && token.equals(serverToken)) {
                request.getSession(true).removeAttribute(uuid);
                return false;
            }
        }
        return true;
    }
}

提供开启规则的注解:

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

    AvoidReSubmitBehavior behavior();

}

定义两种行为:

public enum  AvoidReSubmitBehavior {
    Create,
    Check;
}

拦截器的配置:

<!-- 拦截器配置 -->
    <mvc:interceptors>
        <!-- 配置Token拦截器,防止用户重复提交数据 -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="liam.AvoidReSubmitIntercepter"/>
        </mvc:interceptor>
    </mvc:interceptors>

Java代码使用;

    @AvoidReSubmitToken(behavior = AvoidReSubmitBehavior.Create)
    @RequestMapping("test")
    public String testPage() {
        return "form/page";
    }
    @AvoidReSubmitToken(behavior = AvoidReSubmitBehavior.Check)
    @RequestMapping("potHandler")
    public String postHandler(){
        return "ok";
    }

页面代码:

<form id="" class="form-horizontal" action="${ctx}/postHandler" method="post">
        ......
        <input type="hidden" name="token" value="${identifier_token}"/>
        <!-- 注:name必须是identifier_token -->
        ......
</form>

其实该方案也可以验证提交数据是否有效,当然通常是把token放到只读的缓存了。。

伪代码。。没测试呢。。。

原文地址:https://www.cnblogs.com/ylsforever/p/8532665.html

时间: 2024-09-28 10:44:19

spring MVC 后台token防重复提交解决方案的相关文章

springmvc的token防重复提交

一:首要创立一个号码大全token处置类  ,这儿的类名叫关键词挖掘工具  TokenHandler private static Logger logger = Logger.getLogger(TokenHandler.class); static Map springmvc_token http://www.3h5.cn = null; //生成一个仅有值的token @SuppressWarnings("unchecked") public synchronized stati

spring mvc 后台获取不到form提交的参数

在spring mvc 后台一直获取不到 $("#Form").serialize();提交的参数,一直想来想去都找不到原因.无意当中想起自己使用<input type="text" name="name" value="xxx" disabled="true"/>来禁用了.当把这个属性去掉之后,果然就可以获取到参数的值了. 在这里也顺便比较一下,input中属性disabled与readonl

防重复提交实现方案

在WEB系统操作中,往往会出现用户连续重复点击一个按钮导致重复提交,后台程序的同一个接口代码往往上一个请求还没执行完,下一个请求就到达了,而这两个请求又是请求和操作的同一条数据,就会出现业务上的逻辑错误,往往结果不可预料: 要解决重复提交带来的问题的解决方案有多种,不如网上有很多介绍怎么通过前端页面控制来解决重复提交,当然还有其他方式,这里我采用了通过后台程序代码利用redis做分布式锁的方式来防止重复提交,其思路就是在进入一个后端接口执行前先获取一个分布式锁,如果获取成功则上锁,然后执行业务代

struts2学习(15)struts2防重复提交

一.重复提交的例子: 模拟一种情况,存在延时啊,系统比较繁忙啊啥的. 模拟延迟5s钟,用户点了一次提交,又点了一次提交,例子中模拟这种情况: 这样会造成重复提交: com.cy.action.StudentAction.java: package com.cy.action; import java.io.File; import org.apache.commons.io.FileUtils; import com.cy.model.Student; import com.opensympho

(九)Struts2 防重复提交

所有的学习我们必须先搭建好Struts2的环境(1.导入对应的jar包,2.web.xml,3.struts.xml) 第一节:重复提交示例演示 第二节:使用<s:token/>标签防重复提交 <s:token></s:token> :加在form 里: 使用token 拦截器: <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name=

防重复提交

// 防重复提交 定义全局变量 var checkingCorrespondflg = false; =============== 点击提交判断 if (!checkingCorrespondflg) { checkingCorrespondflg = true; } else { return false; } =============== 出错之后设置 checkingCorrespondflg = false;

struts2中token防止重复提交表单

struts2中token防止重复提交表单 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 蕃薯耀 2015年7月12日 11:52:32 星期日 http://fanshuyao.iteye.com/ 第一步:在表单中加上<s:token></s:token>

Spring MVC与表单日期提交的问题

Spring MVC与表单日期提交的问题 spring mvc 本身并不提供日期类型的解析器,需要手工绑定, 否则会出现非法参数异常. org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [java.util.Date]: Constructor threw exception; nested exception is java.lang.IllegalArgumentExc

防止跨站请求伪造(CSRF)攻击 和 防重复提交 的方法的实现

CSRF的概率可以参考:http://netsecurity.51cto.com/art/200812/102951.htm 本文介绍的是基于spring拦截器的Spring MVC实现 首先配置拦截器: <mvc:interceptors> <mvc:interceptor> <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller --> <mvc:mapping path="/xxx/**" /> <