springmvc 拦截器 防止重复提交表单

 

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

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

注解Token代码:

[java]  view plain  copy
  1. package com.thinkgem.jeesite.common.repeat_form_validator;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. /** 
  9.  * 页面form   token 
  10.  * @author Administrator 
  11.  * 
  12.  */  
  13. @Target(ElementType.METHOD)  
  14. @Retention(RetentionPolicy.RUNTIME)  
  15. public @interface FormToken {  
  16.   
  17.     boolean save() default false;  
  18.   
  19.     boolean remove() default false;  
  20. }  


拦截器TokenInterceptor代码:

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

然后在Spring MVC的配置文件里加入:

[java]  view plain  copy
  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>  


相关代码已经注释,相信你能看懂。
关于这个方法的用法是:
在需要生成token的controller上增加@FormToken(save=true),而在需要检查重复提交的controller上添加@FormToken(remove=true)就可以了。
另外,你需要在view里在form里增加下面代码:

[html]  view plain  copy
  1. <inputtypeinputtype="hidden"name="formToken"value="${formToken}" />  

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

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

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

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

写好自定义注解

[java]  view plain  copy
  1. package com.thinkgem.jeesite.common.repeat_form_validator;  
  2.   
  3. import java.lang.annotation.ElementType;  
  4. import java.lang.annotation.Retention;  
  5. import java.lang.annotation.RetentionPolicy;  
  6. import java.lang.annotation.Target;  
  7.   
  8. /** 
  9.  * 一个用户 相同url 同时提交 相同数据 验证 
  10.  * @author Administrator 
  11.  * 
  12.  */  
  13. @Target(ElementType.METHOD)  
  14. @Retention(RetentionPolicy.RUNTIME)  
  15. public @interface SameUrlData {  
  16.   
  17.       
  18. }  


写好拦截器

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


 springMvc4.x进行代码控制拦截器


@Configuration
public class MvcInterceptorConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("*").excludePathPatterns("/licardUser/loginRegister")
                .excludePathPatterns("/licardUser/getImgCaptcha").excludePathPatterns("/licardcommon/captcha");

        registry.addInterceptor(new FormTokenInterceptor()).addPathPatterns("/licardbussiness/analogCal", "/licardbussiness/cashApply");

        registry.addInterceptor(new SameUrlDataInterceptor()).addPathPatterns("/licardApply/limitApply");
    }
}

判断session中保存的token

生成token

@RequestMapping(value = "/analogCal", method = RequestMethod.POST)
@FormToken(save=true)
public ApiResponse analogCal(String custId, String prodId, Integer periods, double amount, Integer type) {
    
}

一次token

@RequestMapping(value = "/cashApply", method = RequestMethod.POST)
@FormToken(remove=true)
public ApiResponse cashApply(HttpSession session,CashApplyVO cashApplyVO) {
   

}


判断请求url和数据是否和上一次相同调用

@SuppressWarnings("unchecked")
@RequestMapping(value = "/limitApply",method = RequestMethod.POST)
@SameUrlData
public ApiResponse<String> limitApply(String custId,String applyType){
   
}


 第二种方法必须保证不能一个用户在多个浏览器上同时登录,否则不能保证同一个用户一个session

转载自:http://blog.csdn.net/u013378306/article/details/52944780

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值