业务场景介绍

web系统经常会出现用户在页面上快速点击多次提交按钮(或者重复刷新页面),在后台会连续接收多次请求,除了第一次外,其他的相同请求就是重复提交。

如何避免页面重复提交呢,正常有以下几种方法:

  1. 前台控制:点击后,使用js将按钮事件移除
  2. 后台控制:生成token存储session中,使用页面拦截器校验
  3. 后台控制:生成token放入redis中并设置有效期,让其自动失效

方法1过于简单暴力,有一定效果;方法2有点复杂也不是很灵活,其实和方法2有点类似

这里要详细介绍的是方法2,通过拦截器+注解,使用简单灵活。

使用页面拦截器校验token,防止重复提交

基本原理

  1. 通过拦截器拦截页面请求
  2. 在打开页面时生成token,并存储在session中
  3. 页面上提交时将token传到后台,在拦截器中校验token
  4. 如果token不匹配则拒绝请求,并返回错误信息
  5. 如果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());}}

使用拦截器防止表单重复提交相关推荐

  1. 使用Struts2防止表单重复提交

    用户重复提交表单在某些场合将会造成非常严重的后果.例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次.因此,重复提 ...

  2. Spring Boot中防表单重复提交以及拦截器登录检测

    目录 理论 演示 源码 理论 在用户登录后,如果按F5刷新会出现表单重复提交的问题,解决这个问题后,如果没有拦截器登录检测,就会造成,任意用户可以登录后台界面,所以要有拦截器登录检测. 相关的逻辑步骤 ...

  3. struts2 自带的 token防止表单重复提交拦截器

    在struts2中,我们可以利用struts2自带的token拦截器轻松实现防止表单重复提交功能! 1. 在相应的action配置中增加:  <interceptor-ref name=&quo ...

  4. 七、SpringBoot——用户登录Demo(国际化、表单重复提交,登录拦截器)

    一.CURD的Demo 1开发前准备工作 新建一个SpringBoot工程 引入starter-web maven依赖 引入html页面和assert文件夹里的样式文件等等 2 实现访问登录页面 方式 ...

  5. Spring MVC拦截器+注解方式实现防止表单重复提交

    原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过. 1.新建注解: /*** <p&g ...

  6. JavaWeb -- Session实例 -- 自动登录 和 防止表单重复提交(令牌产生器) MD5码

    1. 自动登录 http://blog.csdn.net/xj626852095/article/details/16825659 2. 防止表单重复提交 表单Servlet //负责产生表单 pub ...

  7. 34.TokenInterceptor防止表单重复提交

    转自:https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html 由于某些原因,用户在进行类似表单提交的操作后,以为表单未被提交,会进行多次的 ...

  8. SpringMVC中实现的token,防表单重复提交

    一:首先创建一个token处理类  ,这里的类名叫 TokenHandler private static Logger logger = Logger.getLogger(TokenHandler. ...

  9. 简单介绍redis分布式锁解决表单重复提交的问题

    在系统中,有些接口如果重复提交,可能会造成脏数据或者其他的严重的问题,所以我们一般会对与数据库有交互的接口进行重复处理.本文就详细的介绍一下redis分布式锁解决表单重复提交,感兴趣的可以了解一下 假 ...

最新文章

  1. 强强联合!Papers with Code 携手 arXiv,上传论文、提交代码一步到位
  2. 听说又被 JVM 内存区域方面的面试题给虐了?看看这篇文章吧!
  3. WF4.0进行单元测试
  4. Linux 下用来查询安装包信息的RPM选项
  5. 内置系统账户:Local system/Network service/Local Service 区别
  6. Python中文编码 - Python零基础入门教程
  7. 创建系统镜像_学会这些, 操作docker image镜像就够了!
  8. css3兼容IE8的方案 各个ie的hack
  9. Object.defineProperty()属性设置介绍
  10. 阿里云郑晓:浅谈GPU虚拟化技术(第四章)
  11. Ucient、Netdraw的安装与使用-----分析人物间的关系和重要性
  12. python链家爬虫
  13. Pycharm我认为最好看,最舒服的主题配色和字体设置
  14. graphpad两组t检验_GraphPad prism -- t检验操作步骤解析~
  15. 计算机建模与仿真心得,数学建模学习心得
  16. 如何进阶为数据科学家
  17. 如何提升客户的信任,实现与客户的连接,带动业绩的转变
  18. KNN最近邻算法理解
  19. 云队友丨五大思维模式,决定你的人生能走多远
  20. android获取网卡ip地址吗,Native.js获取android有线网络IP地址

热门文章

  1. 基于大佬的代码实现看板娘效果(三段代码实现)
  2. python计算AUC、Accuracy、Recall、Precision和PPV
  3. matlab2018a课后答案,[2018年最新整理]matlab习题及答案.doc
  4. 一文搞懂K-means聚类算法
  5. 微信小程序开发—— app.json
  6. Linux Centos7 防火墙(开启、关闭、重启、状态、端口)
  7. 上层应用程序是如何访问到底层驱动程序的呢?
  8. java bitmap 保存 jpg_Glide加载图片并保存到本地返回file,bitmap
  9. CSS 控制边框样式
  10. 让你的Onedrive网盘秒变网站,文件展示,直连下载,视频在线播放