• 使用aop注解实现表单防重复提交功能


    原文:https://www.cnblogs.com/manliu/articles/5983888.html

    1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分别放到session和request中,表单页面用一个隐藏域储存该token_flag,在提交表单时,将该token_flag一并提交到后台,后台将该token_flag和session中对比,只要比对通过就立即删除session中的token_flag,这样就能保证表单最多只有一次成功提交的机会。

    2.表单防重复提交一般前后端都会做,前端比较简单,点击过一次就将提交按钮置灰或disabled。

    3.因为生成和验证token_flag具有通用性,一般不建议嵌入到具体方法中,最好的方法就是使用aop+注解的方式

    4.注解

    复制代码
    /**
    * 表单注解,放在需要验证表单的方法上,一般是controller上
    */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface FormToken {
    
    }
    复制代码

    5.AOP

    复制代码
    @Aspect
    @Component    
    public class ResubmitAspect {
        private static final String PARAM_TOKEN = "token";
        private static final String PARAM_TOKEN_FLAG = "TokenFlag_";
    
        /**
         * 执行切面拦截逻辑
         */
        @Around("@annotation(formToken)")
        public void execute(ProceedingJoinPoint joinPoint, FormToken formToken) throws Throwable {   
           if (formToken != null) {
                //方法入参列表
                Object[] args = joinPoint.getArgs();
                //类名
                String className = joinPoint.getTarget().getClass().getName();
                for (Object arg : args) {
                    //方法入参是否包含request
                    if (arg != null && arg instanceof HttpServletRequest) {
                        HttpServletRequest request = (HttpServletRequest) arg;
                        HttpSession session = request.getSession(true);
                        if ("GET".equalsIgnoreCase(request.getMethod())) {
                            /* GET 生成 token */
                            this.generate(joinPoint, request, session, PARAM_TOKEN_FLAG + className);
                        } else {
                            /* POST 验证 token */
                            this.validation(joinPoint, request, session, PARAM_TOKEN_FLAG + className);
                        }
                    }
                }
            }
        }
        /**
         * <p>
         * 生成表单 token
         * </p>
         */
        public void generate(ProceedingJoinPoint joinPoint, HttpServletRequest request, HttpSession session,
                String tokenFlag) throws Throwable {
            String uuid = UUID.randomUUID().toString();
            session.setAttribute(tokenFlag, uuid);
            request.setAttribute(PARAM_TOKEN, uuid);
            joinPoint.proceed();
        } 
    /** * <p> * 验证表单 token * </p> * <p> * 验证结果一致,既为第一次提交,删除会话中存储的token,并继续执行方法。<br> * 否则不做任何处理。 * </p> */ public void validation(ProceedingJoinPoint joinPoint, HttpServletRequest request, HttpSession session, String tokenFlag) throws Throwable { Object sessionFlag = session.getAttribute(tokenFlag); Object requestFlag = request.getParameter(PARAM_TOKEN); if (sessionFlag != null && sessionFlag.equals(requestFlag)) { //删除已验证的token session.removeAttribute(tokenFlag); joinPoint.proceed(); } } }
    复制代码

    6.配置

    在spring配置文件中

    <aop:aspectj-autoproxy />
    <context:component-scan base-package="com.baomidou.framework.aop">
    </context:component-scan>

    7.html中使用

    <input type="hidden" name="token" value="${token}" />
  • 相关阅读:
    Django的filter查询
    第一篇博客
    算法:位运算加减乘除
    ip头、tcp头、udp头详解及定义,结合Wireshark抓包看实际情况
    linux ls -l 详解
    重要常用的Lunix命令
    开博感言(真正第一篇博客园博客)
    校招与内推:软实力的技巧
    最长公共子串——动态规划求解
    最长公共子序列——动态规划求解
  • 原文地址:https://www.cnblogs.com/shihaiming/p/11082724.html
Copyright © 2020-2023  润新知