使用拦截器防止表单重复提交
业务场景介绍
web系统经常会出现用户在页面上快速点击多次提交按钮(或者重复刷新页面),在后台会连续接收多次请求,除了第一次外,其他的相同请求就是重复提交。
如何避免页面重复提交呢,正常有以下几种方法:
- 前台控制:点击后,使用js将按钮事件移除
- 后台控制:生成token存储session中,使用页面拦截器校验
- 后台控制:生成token放入redis中并设置有效期,让其自动失效
方法1过于简单暴力,有一定效果;方法2有点复杂也不是很灵活,其实和方法2有点类似
这里要详细介绍的是方法2,通过拦截器+注解,使用简单灵活。
使用页面拦截器校验token,防止重复提交
基本原理
- 通过拦截器拦截页面请求
- 在打开页面时生成token,并存储在session中
- 页面上提交时将token传到后台,在拦截器中校验token
- 如果token不匹配则拒绝请求,并返回错误信息
- 如果token匹配,则删除或重新生成token
详细代码
1、添加springMvc请求拦截器AvoidDuplicateSubmitInterceptor.java
/*** 页面重复提交拦截器* * @author huangjian**/
public class AvoidDuplicateSubmitInterceptor extends HandlerInterceptorAdapter {private final Logger logger = LoggerFactory.getLogger(getClass());@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();SubmitToken annotation = method.getAnnotation(SubmitToken.class);if (annotation == null) {return true;}HttpSession session = request.getSession(false);if (annotation.value().equals(TokenType.create)) {SessionTokenUtil.createToken(session);return true;}if (isRepeatSubmit(request)) {logger.warn("页面重复提交,url:{}", request.getRequestURI());RenderUtil.renderFailure("页面重复提交", response);return false;}if (annotation.value().equals(TokenType.refresh)) {// 验证成功后,重新生成tokenSessionTokenUtil.createToken(session);} else {// 验证成功后,删除tokenSessionTokenUtil.removeToken(session);}}return true;}/** 判断是否重复提交 */private boolean isRepeatSubmit(HttpServletRequest request) {String serverToken = SessionTokenUtil.getToken(request.getSession(false));if (serverToken == null) {return true;}String clientToken = request.getParameter(SessionTokenUtil.TOKEN_KEY);if (clientToken == null) {return true;}if (!serverToken.equals(clientToken)) {return true;}return false;}
}
2、添加工具类SessionTokenUtil.java
public class SessionTokenUtil {public static final String TOKEN_KEY = "submitToken";/** 生成10位随机数作为token */private static String createToken() {return RandomUtils.generateString(10);}public static void createToken(HttpSession session) {session.setAttribute(SessionTokenUtil.TOKEN_KEY, createToken());}public static void removeToken(HttpSession session) {session.removeAttribute(SessionTokenUtil.TOKEN_KEY);}public static String getToken(HttpSession session) {String serverToken = (String) session.getAttribute(TOKEN_KEY);return serverToken;}
}
3、添加注解SubmitToken.java,以及枚举TokenType.java
@Retention(RetentionPolicy.RUNTIME)
@Target({ METHOD })
public @interface SubmitToken {TokenType value() default TokenType.create;
}
public enum TokenType {create, remove, refresh
}
4、在controller中使用
1)在打开页面方法标记生成token(方法仅是示例)
/** 进入模块 详细/新增 页 */
@SubmitToken(TokenType.create)
@RequestMapping(value = "detail/{id}", method = RequestMethod.GET)
public String detail(@PathVariable("id") Long id, Model model, HttpServletRequest request) {}
2)在提交保存方法标记刷新或删除token(方法仅是示例)
@SubmitToken(TokenType.refresh)
@RequestMapping(value = "save", method = RequestMethod.POST)
public void save(@Valid @ModelAttribute("preload") BsCx entity, HttpServletRequest request,HttpServletResponse response) {try {//TODO 执行保存操作...// 将新的token返回给页面,并在页面刷新tokenString serverToken = SessionTokenUtil.getToken(request.getSession(false));RenderUtil.renderSuccess(serverToken, response);} catch (Exception e) {//}
}
3)在页面上面添加token值,如果需要支持连续操作,要在保存成功后,更新submitToken值
<input type="hidden" id="submitToken" name="submitToken" th:value="${session.submitToken}" />
上面是thymeleaf模板示例代码
5、配置拦截器
下面是springboot配置示例
@Configuration
public class WebAppConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new AvoidDuplicateSubmitInterceptor());}}
使用拦截器防止表单重复提交相关推荐
- 使用Struts2防止表单重复提交
用户重复提交表单在某些场合将会造成非常严重的后果.例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次.因此,重复提 ...
- Spring Boot中防表单重复提交以及拦截器登录检测
目录 理论 演示 源码 理论 在用户登录后,如果按F5刷新会出现表单重复提交的问题,解决这个问题后,如果没有拦截器登录检测,就会造成,任意用户可以登录后台界面,所以要有拦截器登录检测. 相关的逻辑步骤 ...
- struts2 自带的 token防止表单重复提交拦截器
在struts2中,我们可以利用struts2自带的token拦截器轻松实现防止表单重复提交功能! 1. 在相应的action配置中增加: <interceptor-ref name=&quo ...
- 七、SpringBoot——用户登录Demo(国际化、表单重复提交,登录拦截器)
一.CURD的Demo 1开发前准备工作 新建一个SpringBoot工程 引入starter-web maven依赖 引入html页面和assert文件夹里的样式文件等等 2 实现访问登录页面 方式 ...
- Spring MVC拦截器+注解方式实现防止表单重复提交
原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过. 1.新建注解: /*** <p&g ...
- JavaWeb -- Session实例 -- 自动登录 和 防止表单重复提交(令牌产生器) MD5码
1. 自动登录 http://blog.csdn.net/xj626852095/article/details/16825659 2. 防止表单重复提交 表单Servlet //负责产生表单 pub ...
- 34.TokenInterceptor防止表单重复提交
转自:https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html 由于某些原因,用户在进行类似表单提交的操作后,以为表单未被提交,会进行多次的 ...
- SpringMVC中实现的token,防表单重复提交
一:首先创建一个token处理类 ,这里的类名叫 TokenHandler private static Logger logger = Logger.getLogger(TokenHandler. ...
- 简单介绍redis分布式锁解决表单重复提交的问题
在系统中,有些接口如果重复提交,可能会造成脏数据或者其他的严重的问题,所以我们一般会对与数据库有交互的接口进行重复处理.本文就详细的介绍一下redis分布式锁解决表单重复提交,感兴趣的可以了解一下 假 ...
最新文章
- 强强联合!Papers with Code 携手 arXiv,上传论文、提交代码一步到位
- 听说又被 JVM 内存区域方面的面试题给虐了?看看这篇文章吧!
- WF4.0进行单元测试
- Linux 下用来查询安装包信息的RPM选项
- 内置系统账户:Local system/Network service/Local Service 区别
- Python中文编码 - Python零基础入门教程
- 创建系统镜像_学会这些, 操作docker image镜像就够了!
- css3兼容IE8的方案 各个ie的hack
- Object.defineProperty()属性设置介绍
- 阿里云郑晓:浅谈GPU虚拟化技术(第四章)
- Ucient、Netdraw的安装与使用-----分析人物间的关系和重要性
- python链家爬虫
- Pycharm我认为最好看,最舒服的主题配色和字体设置
- graphpad两组t检验_GraphPad prism -- t检验操作步骤解析~
- 计算机建模与仿真心得,数学建模学习心得
- 如何进阶为数据科学家
- 如何提升客户的信任,实现与客户的连接,带动业绩的转变
- KNN最近邻算法理解
- 云队友丨五大思维模式,决定你的人生能走多远
- android获取网卡ip地址吗,Native.js获取android有线网络IP地址
热门文章
- 基于大佬的代码实现看板娘效果(三段代码实现)
- python计算AUC、Accuracy、Recall、Precision和PPV
- matlab2018a课后答案,[2018年最新整理]matlab习题及答案.doc
- 一文搞懂K-means聚类算法
- 微信小程序开发—— app.json
- Linux Centos7 防火墙(开启、关闭、重启、状态、端口)
- 上层应用程序是如何访问到底层驱动程序的呢?
- java bitmap 保存 jpg_Glide加载图片并保存到本地返回file,bitmap
- CSS 控制边框样式
- 让你的Onedrive网盘秒变网站,文件展示,直连下载,视频在线播放