spring mvc 防止重复提交表单的两种方法,推荐第二种
第一种方法:判断session中保存的token
比较麻烦,每次在提交表单时都必须传入上次的token。而且当一个页面使用ajax时,多个表单提交就会有问题。
注解Token代码:
- package com.thinkgem.jeesite.common.repeat_form_validator;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * 页面form token
- * @author Administrator
- *
- */
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface FormToken {
- boolean save() default false;
- boolean remove() default false;
- }
package com.thinkgem.jeesite.common.repeat_form_validator; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
- 页面form token
- @author Administrator
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FormToken {
boolean save() default false;
boolean remove() default false;
}
拦截器TokenInterceptor代码:
- package com.thinkgem.jeesite.common.repeat_form_validator;
- import java.lang.reflect.Method;
- import java.util.UUID;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.method.HandlerMethod;
- import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
- public class FormTokenInterceptor extends HandlerInterceptorAdapter {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- if (handler instanceof HandlerMethod) {
- HandlerMethod handlerMethod = (HandlerMethod) handler;
- Method method = handlerMethod.getMethod();
- FormToken annotation = method.getAnnotation(FormToken.class);
- if (annotation != null) {
- boolean needSaveSession = annotation.save();
- if (needSaveSession) {
- request.getSession(false).setAttribute("formToken", UUID.randomUUID().toString());
- }
- boolean needRemoveSession = annotation.remove();
- if (needRemoveSession) {
- if (isRepeatSubmit(request)) {
- return false;
- }
- request.getSession(false).removeAttribute("formToken");
- }
- }
- return true;
- } else {
- return super.preHandle(request, response, handler);
- }
- }
- private boolean isRepeatSubmit(HttpServletRequest request) {
- String serverToken = (String) request.getSession(false).getAttribute("formToken");
- if (serverToken == null) {
- return true;
- }
- String clinetToken = request.getParameter("formToken");
- if (clinetToken == null) {
- return true;
- }
- if (!serverToken.equals(clinetToken)) {
- return true;
- }
- return false;
- }
- }
package com.thinkgem.jeesite.common.repeat_form_validator; import java.lang.reflect.Method;
import java.util.UUID; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class FormTokenInterceptor extends HandlerInterceptorAdapter {@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
FormToken annotation = method.getAnnotation(FormToken.class);
if (annotation != null) {
boolean needSaveSession = annotation.save();
if (needSaveSession) {
request.getSession(false).setAttribute("formToken", UUID.randomUUID().toString());
}
boolean needRemoveSession = annotation.remove();
if (needRemoveSession) {
if (isRepeatSubmit(request)) {
return false;
}
request.getSession(false).removeAttribute("formToken");
}
}
return true;
} else {
return super.preHandle(request, response, handler);
}
} private boolean isRepeatSubmit(HttpServletRequest request) {
String serverToken = (String) request.getSession(false).getAttribute("formToken");
if (serverToken == null) {
return true;
}
String clinetToken = request.getParameter("formToken");
if (clinetToken == null) {
return true;
}
if (!serverToken.equals(clinetToken)) {
return true;
}
return false;
}
}
然后在Spring MVC的配置文件里加入:
- <mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/**"/>
- <bean class="com.thinkgem.jeesite.common.repeat_form_validator.FormTokenInterceptor"/>
- </mvc:interceptor>
- </mvc:interceptors>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.thinkgem.jeesite.common.repeat_form_validator.FormTokenInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
相关代码已经注释,相信你能看懂。
关于这个方法的用法是:在需要生成token的controller上增加@FormToken(save=true),而在需要检查重复提交的controller上添加@FormToken(remove=true)就可以了。
另外,你需要在view里在form里增加下面代码:
- <inputtypeinputtype="hidden"name="formToken"value="${formToken}" />
<inputtype="hidden"name="formToken"value="${formToken}" />
已经完成了,去试试看你的数据还能重复提交了吧。
注意在ajax提交时 要加上 formToken参数
第二种方法(判断请求url和数据是否和上一次相同)
推荐,非常简单,页面不需要任何传入,只需要在验证的controller方法上写上自定义注解即可
写好自定义注解
- package com.thinkgem.jeesite.common.repeat_form_validator;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- /**
- * 一个用户 相同url 同时提交 相同数据 验证
- * @author Administrator
- *
- */
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface SameUrlData {
- }
package com.thinkgem.jeesite.common.repeat_form_validator; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
- 一个用户 相同url 同时提交 相同数据 验证
- @author Administrator
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SameUrlData { }
写好拦截器
- package com.thinkgem.jeesite.common.repeat_form_validator;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.method.HandlerMethod;
- import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
- import com.thinkgem.jeesite.common.mapper.JsonMapper;
- /**
- * 一个用户 相同url 同时提交 相同数据 验证
- * 主要通过 session中保存到的url 和 请求参数。如果和上次相同,则是重复提交表单
- * @author Administrator
- *
- */
- public class SameUrlDataInterceptor extends HandlerInterceptorAdapter{
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- if (handler instanceof HandlerMethod) {
- HandlerMethod handlerMethod = (HandlerMethod) handler;
- Method method = handlerMethod.getMethod();
- SameUrlData annotation = method.getAnnotation(SameUrlData.class);
- if (annotation != null) {
- if(repeatDataValidator(request))//如果重复相同数据
- return false;
- else
- return true;
- }
- return true;
- } else {
- return super.preHandle(request, response, handler);
- }
- }
- /**
- * 验证同一个url数据是否相同提交 ,相同返回true
- * @param httpServletRequest
- * @return
- */
- public boolean repeatDataValidator(HttpServletRequest httpServletRequest)
- {
- String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap());
- String url=httpServletRequest.getRequestURI();
- Map<String,String> map=new HashMap<String,String>();
- map.put(url, params);
- String nowUrlParams=map.toString();//
- Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData");
- if(preUrlParams==null)//如果上一个数据为null,表示还没有访问页面
- {
- httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);
- return false;
- }
- else//否则,已经访问过页面
- {
- if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+数据和本次url+数据相同,则表示城府添加数据
- {
- return true;
- }
- else//如果上次 url+数据 和本次url加数据不同,则不是重复提交
- {
- httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);
- return false;
- }
- }
- }
- }
package com.thinkgem.jeesite.common.repeat_form_validator; import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.thinkgem.jeesite.common.mapper.JsonMapper; /**
- 一个用户 相同url 同时提交 相同数据 验证
- 主要通过 session中保存到的url 和 请求参数。如果和上次相同,则是重复提交表单
- @author Administrator
public class SameUrlDataInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
SameUrlData annotation = method.getAnnotation(SameUrlData.class);
if (annotation != null) {
if(repeatDataValidator(request))//如果重复相同数据
return false;
else
return true;
}
return true;
} else {
return super.preHandle(request, response, handler);
}
}
/**
* 验证同一个url数据是否相同提交 ,相同返回true
* @param httpServletRequest
* @return
*/
public boolean repeatDataValidator(HttpServletRequest httpServletRequest)
{
String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap());
String url=httpServletRequest.getRequestURI();
Map<String,String> map=new HashMap<String,String>();
map.put(url, params);
String nowUrlParams=map.toString();//
Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData");
if(preUrlParams==null)//如果上一个数据为null,表示还没有访问页面
{
httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);
return false;
}
else//否则,已经访问过页面
{
if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+数据和本次url+数据相同,则表示城府添加数据
{
return true;
}
else//如果上次 url+数据 和本次url加数据不同,则不是重复提交
{
httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);
return false;
}
}
}
}
配置spring mvc
- <mvc:interceptor>
- <mvc:mapping path="/**"/>
- <bean class="com.thinkgem.jeesite.common.repeat_form_validator.SameUrlDataInterceptor"/>
- </mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.thinkgem.jeesite.common.repeat_form_validator.SameUrlDataInterceptor"/>
</mvc:interceptor>
spring mvc 防止重复提交表单的两种方法,推荐第二种的更多相关文章
- 防止php重复提交表单更安全的方法
Token.php <?php /* * Created on 2013-3-25 * * To change the template for this generated file go t ...
- C#根据字体名通过注册表获取该字体文件路径(win10)两种方法推荐第二种
方法一: 直接先上源码: private System.Collections.Generic.SortedDictionary<string, string> ReadFontInfor ...
- Struts2 token禁止重复提交表单
如果服务器响应慢的情况下,用户会重复提交多个表单,这时候有两种设计思想: 1.在客户端使用JS技术,禁止客户重复提交表单.但是这样会使一些不使用浏览器方式登陆的人比如使用底层通信来攻击你的服务器 2. ...
- PHP防止用户重复提交表单
我们提交表单的时候,不能忽视的一个限制是防止用户重复提交表单,因为有可能用户连续点击了提交按钮或者是攻击者恶意提交数据,那么我们在提交数据后的处理如修改或添加数据到数据库时就会惹上麻烦. 那么如何规避 ...
- struts2中token防止重复提交表单
struts2中token防止重复提交表单 >>>>>>>>>>>>>>>>>>>&g ...
- 关于Asp.Net中避免用户连续多次点击按钮,重复提交表单的处理
Web页面中经常碰到这类问题,就是客户端多次点击一个按钮或者链接,导致程序出现不可预知的麻烦. 客户就是上帝,他们也不是有意要给你的系统造成破坏,这么做的原因很大一部分是因为网络慢,点击一个操作之后, ...
- JavaWeb 之 重复提交表单和验证码相关的问题!
下面我们首先来说一下表单的重复提交问题,我们知道在真实的网络环境中可能受网速带宽的原因会造成页面中表单在提交的过程中出现网络的延迟等问题,从而造成多次提交的问题!下面我们就具体来分析一下造成表单提交的 ...
- php防止重复提交表单
解决方案一:引入cookie机制来解决 提交页面代码如下a.php代码如下: <form id="form1" name="form1" method=& ...
- JavaWeb -- Struts1 使用示例: 表单校验 防表单重复提交 表单数据封装到实体
1. struts 工作流程图 超链接 2. 入门案例 struts入门案例: 1.写一个注册页面,把请求交给 struts处理 <form action="${pageContext ...
随机推荐
- SpringCloud学习笔记(7)----Spring Cloud Netflix之负载均衡-Ribbon的深入理解
1. 注解@LoadBalanced 作用:识别应用名称,并进行负载均衡. 2. 入口类:LoadBalancerAutoConfiguration 说明:类头上的注解可以知道Ribbon 实现的负载 ...
- 2017年6月28日 python爬虫学习
1.写入csv文件2.lxml的用法3.自定义字典类的方法4.bytes解码得到str,str编码得到bytes5.json 1 import csv import lxml.html class S ...
- PHP SOAP 教程
一.SoapServer 服务器 1.__construct 作用:创建 SoapServer 对象 用法:__construct ( mixed wsdl [, array options] ) 参 ...
- 基础命令:chown
chown:改变文件或目录的用户和用户组 [语法格式] chown [option] [OWNER][:[GROUP]] [file] chown [选项] [用户 : 用户组 ] [<文 ...
- [luogu] P2787 语文1(chin1)- 理理思维(分块)
P2787 语文1(chin1)- 理理思维 题目背景 蒟蒻HansBug在语文考场上,挠了无数次的头,可脑子里还是一片空白. 题目描述 考试开始了,可是蒟蒻HansBug脑中还是一片空白.哦不!准确 ...
- Android平台Camera实时滤镜实现方法探讨(九)--磨皮算法探讨(一)
上一篇开头提到了一些可用于磨皮的去噪算法.以下我们实现这些算法而且观察效果,咱不考虑实时性的问题 本文首先探讨的首先是<基于局部均方差相关信息的图像去噪及其在实时磨皮美容算法中的应用> 该 ...
- Codeforces Round #249 (Div. 2) (模拟)
C. Cardiogram time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- mysql-用正则表达式进行搜索
正则表达式的作用是匹配文本,将一个模式(正则表达式)与一个文本串进行比较,mysql允许你指定正则表达式,过滤select检索出的数据.但是mysql仅仅支持正则表达式的一个子集. 1.基本字符匹配: ...
- hdu5371Hotaru's problem manacher算法
//给一个序列.让求其最大子序列 //这个序列由三段组成.第一段和第二段对称,第一段和第三段一样 //manacher算法求得p[i] //枚举第二段的起点和长度,得到结果 #include<c ...
- hdu_1698线段树成段更新
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #d ...