admin 管理员组文章数量: 1087580
防止form表单提交的几种方式
1. 背景介绍
在开发项目中肯可能会出现如下情况:
1. 用户的失误操作,多次点击表单提交按钮
2. 由于网速等原因造成页面卡顿,用户重复刷新提交页面
3. 黑客或恶意用户使用postman等工具重复恶意提交表单
....
这些情况都会导致表单的重复提交,导致数据重复,增加服务器的压力,甚至会造成服务器宕机,因此要有效防止表单重复提交非常必要。
2. 解决方案
2.1 点击一次之后,按钮失效(不推荐,用户刷新页面仍能重复提交)
通过js代码,当用户点击提交按钮后,屏蔽提交按钮(使按钮无发点击提交或点击无效disabled),从而实现防止表单重复提交。
2.2 用redirect来解决重复提交问题
简而言之,表单提交后重定向到提交成功的一个页面。
2.3在数据库里添加约束
在数据库里添加唯一约束或创建唯一索引,防止出现重复数据。简单粗暴的方法。
2.4 在session中存放一个特殊标志(推荐)。
类似于“令牌”机制。当表单页面第一次被请求时,生成一个特殊的字符标志串,存在session中,同时放在表单的隐藏域里。接受处理表单数据时,检查标识字串是否存在,若标志串相同则处理表单提交并立即从session中删除它。若不一致就是重复提交了则忽略这次提交。如果发现表单提交里没有有效的标志串,这说明表单已经被提交过了,忽略这次提交。
(解决struts2重复提交,可以结合s:token标签解决重复提交问题)
2.5 使用AOP自定义切入实现
实现原理:
- 自定义防止重复提交标记(@AvoidRepeatableCommit)。
- 对需要防止重复提交的Congtroller里的mapping方法加上该注解。
- 新增Aspect切入点,为@AvoidRepeatableCommit加入切入点。
- 每次提交表单时,Aspect都会保存当前key到reids(须设置过期时间)。
- 重复提交时Aspect会判断当前redis是否有该key,若有则拦截。
自定义标签
import java.lang.annotation.*;/*** 避免重复提交* @author dsx* @version* @since*/@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface AvoidRepeatableCommit {/*** 指定时间内不可重复提交,单位毫秒* @return*/long timeout() default 30000 ;}
自定义切面Aspect
/*** 解决重复提交aop* @author dsx* @version * @since */@Aspect@Componentpublic class AvoidRepeatableCommitAspect {@Autowiredprivate RedisTemplate redisTemplate;/*** @param point*/@Around("@annotation(com.xwolf.boot.annotation.AvoidRepeatableCommit)")public Object around(ProceedingJoinPoint point) throws Throwable {HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();String ip = IPUtil.getIP(request);//获取注解MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();//目标类、方法String className = method.getDeclaringClass().getName();String name = method.getName();String ipKey = String.format("%s#%s",className,name);int hashCode = Math.abs(ipKey.hashCode());String key = String.format("%s_%d",ip,hashCode);log.info("ipKey={},hashCode={},key={}",ipKey,hashCode,key);AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);long timeout = avoidRepeatableCommit.timeout();if (timeout < 0){//过期时间5分钟timeout = 60*5;}String value = (String) redisTemplate.opsForValue().get(key);if (StringUtils.isNotBlank(value)){return "请勿重复提交";}redisTemplate.opsForValue().set(key, UUIDUtil.uuid(),timeout,TimeUnit.MILLISECONDS);//执行方法Object object = point.proceed();return object;}}
如有不足,望不吝赐教!!!
本文标签: 防止form表单提交的几种方式
版权声明:本文标题:防止form表单提交的几种方式 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1686652583a20654.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论