spring MVC 后台token防重复提交解决方案
看到公司有个部门提出了这个问题,补个粗略的解决方案。。。
1.编写拦截器
/**
* Description: 防止重复提交
*
* @Author liam
* @Create Date: 2018/3/9 9:22
*/
public class AvoidReSubmitIntercepter extends HandlerInterceptorAdapter { private static final String SPLIT_FLAG = "_";
private static final String AVOID_RE_SUBMIT_TOKEN_KEY = "identifier_token"; @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (checkAvoidReSubmitTokenOn(handler,AvoidReSubmitBehavior.Check)) {
//验证是否重复
if (checkIsRepeatSubmit(request)) {
//重复提交
return false;
}
}
return super.preHandle(request, response, handler);
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
if (checkAvoidReSubmitTokenOn(handler,AvoidReSubmitBehavior.Create)) {
Random random = new Random();
String uuid = UUID.randomUUID().toString().replace(SPLIT_FLAG, String.valueOf(random.nextInt()));
String tokenValue = String.valueOf(System.currentTimeMillis());
String transferToken = uuid + SPLIT_FLAG + tokenValue;
request.setAttribute(AVOID_RE_SUBMIT_TOKEN_KEY, transferToken);
request.getSession(true).setAttribute(uuid, tokenValue);
}
super.postHandle(request, response, handler, modelAndView);
} /**
* Description: 是否开启防重规则
*
* @Author liam
* @Create Date: 2018/3/9 10:33
*/
private boolean checkAvoidReSubmitTokenOn(Object handler,AvoidReSubmitBehavior behavior) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method invokeMethod = handlerMethod.getMethod();
AvoidReSubmitToken avoidReSubmitToken = invokeMethod.getAnnotation(AvoidReSubmitToken.class);
if (avoidReSubmitToken != null && avoidReSubmitToken.behavior().equals(behavior)) {
return true;
}
return false; } private boolean checkIsRepeatSubmit(HttpServletRequest request) {
String clientToken = request.getParameter(AVOID_RE_SUBMIT_TOKEN_KEY);
if (StringUtils.isEmpty(clientToken)) {
clientToken = request.getParameter(AVOID_RE_SUBMIT_TOKEN_KEY);
if (StringUtils.isEmpty(clientToken)) {
return true;
}
}
String[] clientTokensDetail = StringUtils.split(clientToken, SPLIT_FLAG);
if (clientTokensDetail.length == ) {
String uuid = clientTokensDetail[];
String token = clientTokensDetail[];
//此处存在并发风险...阔以加锁处理
String serverToken = (String) request.getSession(true).getAttribute(uuid);
if (StringUtils.isNotEmpty(serverToken) && token.equals(serverToken)) {
request.getSession(true).removeAttribute(uuid);
return false;
}
}
return true;
}
}
提供开启规则的注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AvoidReSubmitToken { AvoidReSubmitBehavior behavior(); }
定义两种行为:
public enum AvoidReSubmitBehavior {
Create,
Check;
}
拦截器的配置:
<!-- 拦截器配置 -->
<mvc:interceptors>
<!-- 配置Token拦截器,防止用户重复提交数据 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="liam.AvoidReSubmitIntercepter"/>
</mvc:interceptor>
</mvc:interceptors>
Java代码使用;
@AvoidReSubmitToken(behavior = AvoidReSubmitBehavior.Create)
@RequestMapping("test")
public String testPage() {
return "form/page";
}
@AvoidReSubmitToken(behavior = AvoidReSubmitBehavior.Check)
@RequestMapping("potHandler")
public String postHandler(){
return "ok";
}
页面代码:
<form id="" class="form-horizontal" action="${ctx}/postHandler" method="post">
......
<input type="hidden" name="token" value="${identifier_token}"/>
<!-- 注:name必须是identifier_token -->
......
</form>
其实该方案也可以验证提交数据是否有效,当然通常是把token放到只读的缓存了。。
伪代码。。没测试呢。。。
spring MVC 后台token防重复提交解决方案的更多相关文章
- SpringMVC后台token防重复提交解决方案
本文介绍如何使用token来防止前端重复提交的问题. 目录 1.思路 2.拦截器源码实现 3.注解源码 4.拦截器的配置 5.使用指南 6.结语 思路 1.添加拦截器,拦截需要防重复提交的请求 2.通 ...
- Spring MVC表单防重复提交
利用Spring MVC的过滤器及token传递验证来实现表单防重复提交. 创建注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RU ...
- spring mvc防止表单重复提交的代码片段
1.定义一个token接口 package com.bigbigrain.token; import java.lang.annotation.Documented; import java.lang ...
- (亿级流量)分布式防重复提交token设计
大型互联网项目中,很多流量都达到亿级.同一时间很多的人在使用,而每个用户提交表单的时候都可能会出现重复点击的情况,此时如果不做好控制,那么系统将会产生很多的数据重复的问题.怎样去设计一个高可用的防重复 ...
- 架构设计 | 接口幂等性原则,防重复提交Token管理
本文源码:GitHub·点这里 || GitEE·点这里 一.幂等性概念 1.幂等简介 编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同.就是说,一次和多次请求某一个资源会产 ...
- 使用aop注解实现表单防重复提交功能
原文:https://www.cnblogs.com/manliu/articles/5983888.html 1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分 ...
- (九)Struts2 防重复提交
所有的学习我们必须先搭建好Struts2的环境(1.导入对应的jar包,2.web.xml,3.struts.xml) 第一节:重复提交示例演示 struts.xml <?xml version ...
- AJAX防重复提交的办法总结
最近的维护公司的一个代理商平台的时候,客服人员一直反映说的统计信息的时候有重复数据,平台一直都很正常,这个功能是最近新进的一个实习生同事写的功能,然后就排查问题人所在,发现新的这个模块的AJAX提交数 ...
- struts2学习(15)struts2防重复提交
一.重复提交的例子: 模拟一种情况,存在延时啊,系统比较繁忙啊啥的. 模拟延迟5s钟,用户点了一次提交,又点了一次提交,例子中模拟这种情况: 这样会造成重复提交: com.cy.action.St ...
随机推荐
- H5新增属性classList
H5新增属性classList h5中新增了一个classList,原生js可以通过它来判断获取dom节点有无某个class. classList是html元素对象的成员,它的使用非常简单,比如 co ...
- ios 9 http
记录: <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLo ...
- Flutter自定义标题栏之处理状态栏高度
App在很多情况下由于各种需求需要自定义标题栏,而在能够构建Android和IOS应用的Flutter中,如果不在Scaffold中使用AppBar会发现默认是沉浸式. 猜想:我们使用自定义标题栏好像 ...
- redis HyperLogLog 基数估算
HyperLogLog 可以接受多个元素的输入,返回输入元素的基数估算值基数,集合中不同元素的数量.如集合{1,2,3,1,2,3,4}的基数是4.估算,HyperLogLog算法返回的基数不是完全精 ...
- 【Python】Java程序员学习Python(九)— 集合(list、tuple、range)和映射(dict)
集合是一门语言最重要的一个特性,对集合支持的程度越好,使用起来越方便 一.表现形式 1.1 list list的基本用法: 使用中括号包裹,[1,2,3] 元素类型可以是任意类型,同样可以是list ...
- springboot学习入门之四---开发Web应用之Thymeleaf篇
http://tengj.top/2017/03/13/springboot4/ 1项目结构 说明: root package结构:com.dudu 应用启动类Application.java置于ro ...
- mysqlbinlog usage
[root@localhost mysql3306]# mysqlbinlogmysqlbinlog Ver 3.4 for el7 at x86_64Copyright (c) 2000, 2018 ...
- 转:在决定使用ClickOnce发布你的软件前,应该知道的一些事情(一些常见问题解决方法)
1,无法有效避免非法的下载 使用ClickOnce部署,你的软件的更新版可以发布到Web服务器上,当用户从开始菜单启动软件时,ClickOnce自动到指定的URL去检测是否存在新版本,并且从这个地址下 ...
- iOS系统声音列表
iOS系统声音列表 效果 说明 1. 点击cell就能发出声音 2. 只需要给出声音编号,就可以,非常简单易用 源码 https://github.com/YouXianMing/iOS-Utilit ...
- Celery学习--- Celery 最佳实践之与django结合实现异步任务
django 可以轻松跟celery结合实现异步任务,只需简单配置即可 同步执行和异步执行 注意:即使Celery的任务没有执行完成,但是已经创建了任务ID.可以利用前台的定时任务发送Ajax异步请求 ...