zoukankan      html  css  js  c++  java
  • Spring MVC防止数据重复提交

         现实开发中表单重复提交的例子很多,就包括手上这个门户的项目也有这种应用场景,用的次数多,但是总结,这还是第一次。

    一、基本原理

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

    二、代码

    2.1、注解Token代码:

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Token {
    
        boolean save() default false;
    
        boolean remove() default false;
    }
    

    2.2、拦截器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;
        }
    }
    

    2.3、在Spring MVC的配置文件里加入:

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

    2.4、使用:

      在需要生成token的controller上增加@Token(save=true),而在需要检查重复提交的controller上添加@Token(remove=true)就可以了。
    另外,你需要在view里在form里增加下面代码:

    <input type="hidden" name="token" value="${token}" />
    

      

  • 相关阅读:
    发现个atan2的正确使用方式
    Forward+ Shading架构
    fatal: unable to connect to gitee.com: gitee.com[0: 180.97.125.228]: errno=Unknown error 解决方案
    HDFS HA(高可用性)集群规划
    如何使用RTP引擎对语音编码进行转码
    关于 Angular 应用 tsconfig.json 中的 target 属性
    浅谈 Orbeon form builder 的权限控制
    关于 Angular 应用 tsconfig.json 中的 lib 属性
    orbeon form 通过 url 的方式同第三方应用集成的开发明细
    orbeon form 的配置介绍
  • 原文地址:https://www.cnblogs.com/geekdc/p/5773583.html
Copyright © 2011-2022 走看看