博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AOP+Token防止表单重复提交
阅读量:4334 次
发布时间:2019-06-07

本文共 3926 字,大约阅读时间需要 13 分钟。

表单重复提交:

由于用户误操作,多次点击表单提交按钮

由于网速等原因造成页面卡顿,用户重复刷新提交页面

 

避免表单重复提交的方式:

1.页面上的按钮做防重复点击操作

2.在数据库中可以做唯一约束

3.利用token校验重复提交

 

如何利用token校验表单重复提交

思路:在表单提交前先请求后台获取token,后台随机生成token保存在session中,提交表单时在请求参数中带上获取的token即可,后台校验token是否匹配。

token的获取和校验可以统一写在AOP切面类中。

 

自定义注解

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

 

切面类

@Aspect@Componentpublic class TokenAspect {    @SuppressWarnings("unused")    @Before("within(@org.springframework.stereotype.Controller *) && @annotation(token)")    public void testToken(final JoinPoint joinPoint, Token token){        try {            if (token != null) {                //获取 joinPoint 的全部参数                Object[] args = joinPoint.getArgs();                HttpServletRequest request = null;                HttpServletResponse response = null;                for (int i = 0; i < args.length; i++) {                    //获得参数中的 request && response                    if (args[i] instanceof HttpServletRequest) {                        request = (HttpServletRequest) args[i];                    }                    if (args[i] instanceof HttpServletResponse) {                        response = (HttpServletResponse) args[i];                    }                }                boolean needSaveSession = token.save();                if (needSaveSession){                    String uuid = UUID.randomUUID().toString();                    request.getSession().setAttribute( "token" , uuid);                    System.out.println("进入表单页面,Token值为:"+uuid);                }                boolean needRemoveSession = token.remove();                if (needRemoveSession) {                    if (isRepeatSubmit(request)) {                        System.out.println("表单重复提交");                        throw new FormRepeatException("表单重复提交");                    }                    request.getSession(false).removeAttribute( "token" );                }            }        } catch (FormRepeatException e){            throw e;        } catch (Exception e){            e.printStackTrace();            throw e;        }    }    private boolean isRepeatSubmit(HttpServletRequest request) throws FormRepeatException {        String serverToken = (String) request.getSession( false ).getAttribute( "token" );        if (serverToken == null ) {            return true;        }        String clinetToken = request.getParameter( "token" );        if (clinetToken == null || clinetToken.equals("")) {            return true;        }        if (!serverToken.equals(clinetToken)) {            return true ;        }        System.out.println("校验是否重复提交:表单页面Token值为:"+clinetToken + ",Session中的Token值为:"+serverToken);        return false ;    }}

 

全局异常处理

@ControllerAdvicepublic class ControllerAdviceHandler {        @ResponseBody    @ExceptionHandler(value={com.irish.exception.FormRepeatException.class})    public String arithmeticExceptionHandler(Exception e){           return "您重复提交表单了!";    }}

 

自定义异常

public class FormRepeatException extends RuntimeException {    private static final long serialVersionUID = 1L;    public FormRepeatException(String message){ super(message);}        }

 

controller层

@Controllerpublic class URLController {        /**     * 获取token,并将token保存在session中     * @return     */    @Token(save = true)    @RequestMapping("/queryToken")    @ResponseBody    public String getToken(HttpServletRequest request, HttpServletResponse response){        return (String) request.getSession().getAttribute("token");    }    /**     * 提交表单的地址,在AOP中检查表单是否重复提交,将token删除     * @param request     * @param response     * @return     */    @Token(remove = true)    @RequestMapping("/submitFrom")    @ResponseBody    public String removeToken(HttpServletRequest request, HttpServletResponse response){        return "success";    }}

 

项目结构:

 github下载地址:

转载于:https://www.cnblogs.com/moris5013/p/11088334.html

你可能感兴趣的文章
[BZOJ4303]数列
查看>>
一般处理程序在VS2012中打开问题
查看>>
C语言中的++和--
查看>>
thinkphp3.2.3入口文件详解
查看>>
POJ 1141 Brackets Sequence
查看>>
Ubuntu 18.04 root 使用ssh密钥远程登陆
查看>>
Servlet和JSP的异同。
查看>>
虚拟机centOs Linux与Windows之间的文件传输
查看>>
ethereum(以太坊)(二)--合约中属性和行为的访问权限
查看>>
IOS内存管理
查看>>
middle
查看>>
[Bzoj1009][HNOI2008]GT考试(动态规划)
查看>>
Blob(二进制)、byte[]、long、date之间的类型转换
查看>>
OO第一次总结博客
查看>>
day7
查看>>
iphone移动端踩坑
查看>>
vs无法加载项目
查看>>
Beanutils基本用法
查看>>
玉伯的一道课后题题解(关于 IEEE 754 双精度浮点型精度损失)
查看>>
《BI那点儿事》数据流转换——百分比抽样、行抽样
查看>>