第一种方法:判断session中保存的token

比较麻烦,每次在提交表单时都必须传入上次的token。而且当一个页面使用ajax时,多个表单提交就会有问题。

注解Token代码:

  1. package com.thinkgem.jeesite.common.repeat_form_validator;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. /**
  7. * 页面form   token
  8. * @author Administrator
  9. *
  10. */
  11. @Target(ElementType.METHOD)
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface FormToken {
  14. boolean save() default false;
  15. boolean remove() default false;
  16. }
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代码:

  1. package com.thinkgem.jeesite.common.repeat_form_validator;
  2. import java.lang.reflect.Method;
  3. import java.util.UUID;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import org.springframework.web.method.HandlerMethod;
  7. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
  8. public class FormTokenInterceptor extends HandlerInterceptorAdapter {
  9. @Override
  10. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  11. if (handler instanceof HandlerMethod) {
  12. HandlerMethod handlerMethod = (HandlerMethod) handler;
  13. Method method = handlerMethod.getMethod();
  14. FormToken annotation = method.getAnnotation(FormToken.class);
  15. if (annotation != null) {
  16. boolean needSaveSession = annotation.save();
  17. if (needSaveSession) {
  18. request.getSession(false).setAttribute("formToken", UUID.randomUUID().toString());
  19. }
  20. boolean needRemoveSession = annotation.remove();
  21. if (needRemoveSession) {
  22. if (isRepeatSubmit(request)) {
  23. return false;
  24. }
  25. request.getSession(false).removeAttribute("formToken");
  26. }
  27. }
  28. return true;
  29. } else {
  30. return super.preHandle(request, response, handler);
  31. }
  32. }
  33. private boolean isRepeatSubmit(HttpServletRequest request) {
  34. String serverToken = (String) request.getSession(false).getAttribute("formToken");
  35. if (serverToken == null) {
  36. return true;
  37. }
  38. String clinetToken = request.getParameter("formToken");
  39. if (clinetToken == null) {
  40. return true;
  41. }
  42. if (!serverToken.equals(clinetToken)) {
  43. return true;
  44. }
  45. return false;
  46. }
  47. }
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的配置文件里加入:

  1. <mvc:interceptors>
  2. <mvc:interceptor>
  3. <mvc:mapping path="/**"/>
  4. <bean class="com.thinkgem.jeesite.common.repeat_form_validator.FormTokenInterceptor"/>
  5. </mvc:interceptor>
  6. </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里增加下面代码:

  1. <inputtypeinputtype="hidden"name="formToken"value="${formToken}" />
<inputtype="hidden"name="formToken"value="${formToken}" />

已经完成了,去试试看你的数据还能重复提交了吧。

注意在ajax提交时 要加上 formToken参数

第二种方法(判断请求url和数据是否和上一次相同)

推荐,非常简单,页面不需要任何传入,只需要在验证的controller方法上写上自定义注解即可

写好自定义注解

  1. package com.thinkgem.jeesite.common.repeat_form_validator;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. /**
  7. * 一个用户 相同url 同时提交 相同数据 验证
  8. * @author Administrator
  9. *
  10. */
  11. @Target(ElementType.METHOD)
  12. @Retention(RetentionPolicy.RUNTIME)
  13. public @interface SameUrlData {
  14. }
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 { }

写好拦截器

  1. package com.thinkgem.jeesite.common.repeat_form_validator;
  2. import java.lang.reflect.Method;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import org.springframework.web.method.HandlerMethod;
  8. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
  9. import com.thinkgem.jeesite.common.mapper.JsonMapper;
  10. /**
  11. * 一个用户 相同url 同时提交 相同数据 验证
  12. * 主要通过 session中保存到的url 和 请求参数。如果和上次相同,则是重复提交表单
  13. * @author Administrator
  14. *
  15. */
  16. public class SameUrlDataInterceptor  extends HandlerInterceptorAdapter{
  17. @Override
  18. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  19. if (handler instanceof HandlerMethod) {
  20. HandlerMethod handlerMethod = (HandlerMethod) handler;
  21. Method method = handlerMethod.getMethod();
  22. SameUrlData annotation = method.getAnnotation(SameUrlData.class);
  23. if (annotation != null) {
  24. if(repeatDataValidator(request))//如果重复相同数据
  25. return false;
  26. else
  27. return true;
  28. }
  29. return true;
  30. } else {
  31. return super.preHandle(request, response, handler);
  32. }
  33. }
  34. /**
  35. * 验证同一个url数据是否相同提交  ,相同返回true
  36. * @param httpServletRequest
  37. * @return
  38. */
  39. public boolean repeatDataValidator(HttpServletRequest httpServletRequest)
  40. {
  41. String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap());
  42. String url=httpServletRequest.getRequestURI();
  43. Map<String,String> map=new HashMap<String,String>();
  44. map.put(url, params);
  45. String nowUrlParams=map.toString();//
  46. Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData");
  47. if(preUrlParams==null)//如果上一个数据为null,表示还没有访问页面
  48. {
  49. httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);
  50. return false;
  51. }
  52. else//否则,已经访问过页面
  53. {
  54. if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+数据和本次url+数据相同,则表示城府添加数据
  55. {
  56. return true;
  57. }
  58. else//如果上次 url+数据 和本次url加数据不同,则不是重复提交
  59. {
  60. httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);
  61. return false;
  62. }
  63. }
  64. }
  65. }
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&lt;String,String&gt; map=new HashMap&lt;String,String&gt;();
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

  1. <mvc:interceptor>
  2. <mvc:mapping path="/**"/>
  3. <bean class="com.thinkgem.jeesite.common.repeat_form_validator.SameUrlDataInterceptor"/>
  4. </mvc:interceptor>
 <mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.thinkgem.jeesite.common.repeat_form_validator.SameUrlDataInterceptor"/>
</mvc:interceptor>

spring mvc 防止重复提交表单的两种方法,推荐第二种的更多相关文章

  1. 防止php重复提交表单更安全的方法

    Token.php <?php /* * Created on 2013-3-25 * * To change the template for this generated file go t ...

  2. C#根据字体名通过注册表获取该字体文件路径(win10)两种方法推荐第二种

    方法一: 直接先上源码: private System.Collections.Generic.SortedDictionary<string, string> ReadFontInfor ...

  3. Struts2 token禁止重复提交表单

    如果服务器响应慢的情况下,用户会重复提交多个表单,这时候有两种设计思想: 1.在客户端使用JS技术,禁止客户重复提交表单.但是这样会使一些不使用浏览器方式登陆的人比如使用底层通信来攻击你的服务器 2. ...

  4. PHP防止用户重复提交表单

    我们提交表单的时候,不能忽视的一个限制是防止用户重复提交表单,因为有可能用户连续点击了提交按钮或者是攻击者恶意提交数据,那么我们在提交数据后的处理如修改或添加数据到数据库时就会惹上麻烦. 那么如何规避 ...

  5. struts2中token防止重复提交表单

    struts2中token防止重复提交表单 >>>>>>>>>>>>>>>>>>>&g ...

  6. 关于Asp.Net中避免用户连续多次点击按钮,重复提交表单的处理

    Web页面中经常碰到这类问题,就是客户端多次点击一个按钮或者链接,导致程序出现不可预知的麻烦. 客户就是上帝,他们也不是有意要给你的系统造成破坏,这么做的原因很大一部分是因为网络慢,点击一个操作之后, ...

  7. JavaWeb 之 重复提交表单和验证码相关的问题!

    下面我们首先来说一下表单的重复提交问题,我们知道在真实的网络环境中可能受网速带宽的原因会造成页面中表单在提交的过程中出现网络的延迟等问题,从而造成多次提交的问题!下面我们就具体来分析一下造成表单提交的 ...

  8. php防止重复提交表单

    解决方案一:引入cookie机制来解决 提交页面代码如下a.php代码如下: <form id="form1" name="form1" method=& ...

  9. JavaWeb -- Struts1 使用示例: 表单校验 防表单重复提交 表单数据封装到实体

    1. struts 工作流程图 超链接 2. 入门案例 struts入门案例: 1.写一个注册页面,把请求交给 struts处理 <form action="${pageContext ...

随机推荐

  1. [ Linux ] user, password, sudoers

    - 1. Add Linux user,  setup password http://linux.vbird.org/linux_basic/0410accountmanager.php - 2. ...

  2. 使用python进行分页操作

    class getPage: """通过这个类 获取 开始和结束点""" def __init__(self,page): try: sel ...

  3. the prblem 3n+1

    题目描述计算机科学中的问题通常被归类为属于某一类问题(例如,NP,不可解,递归).在这个问题中,您将分析算法的属性,该算法的分类对于所有可能的输入都是未知的. 考虑下面的算法: 1.输入n 2.输出n ...

  4. JavaScript 中表达式和语句的区别

    1.语句和表达式 JavaScript中的表达式和语句是有区别的.一个表达式会产生一个值,它可以放在任何需要一个值的地方,比如,作为一个函数调用的参数.下面的每行代码都是一个表达式: myvar3 + ...

  5. spring boot ---web应用开发-错误处理

    一.错误的处理 方法一:Spring Boot 将所有的错误默认映射到/error, 实现ErrorController @Controller @RequestMapping(value = &qu ...

  6. 成长日记--记录在WB的第一个项目。

    具体为什么跑去外包,只能说自己太水了,或者太懒了,都不好好投简历,也没入这个坑过,如果有想去外包的,除非钱给到市场价的1.5倍以上,否则别考虑了. 项目是国内第一做通信公司的,从具体的需求说起比较好, ...

  7. [luogu] P4514 上帝造题的七分钟 (树状数组,二维差分)

    P4514 上帝造题的七分钟 题目背景 裸体就意味着身体. 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a ...

  8. CloudStack云基础架构的一些概念

    1. Zones(区域) 一个区域在CloudStack配置中是最大的组织单元.一个区域通常代表一个单独的数据中心,虽然在一个数据中心也允许有多个区域.将基础架构设施加入到区域中的好处是提供物理隔离和 ...

  9. Qt之表单布局(QFormLayout)

    简述 QFormLayout管理输入型控件和关联的标签组成的那些Form表单. QFormLayout是一个方便的布局类,其中的控件以两列的形式被布局在表单中.左列包括标签,右列包含输入控件,例如:Q ...

  10. Effective C++ 11-17

    11.为须要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符. 显然,由于动态内存分配,绝对会有深浅拷贝的问题,要重写拷贝构造函数.使其为深拷贝,才干实现真正意义上的拷贝.这是我理解的关于要声明拷 ...