Token注解防止表单的重复提交

来源:互联网 发布:windows 10 安装.net 编辑:程序博客网 时间:2024/06/01 09:44

注解的一些基础:

参见java注解(一)和java注解(二)这两篇文章

1,自定义一个注解@Token 用来标记需要防止重复提交的方法

 1 package com.bjca.framework.util; 2 /** 3  * <p> 4 *关于这个方法的用法是: 5 *在需要生成token的controller上增加@Token(save=true), 6 *而在需要检查重复提交的controller上添加@Token(remove=true)就可以了 7 *另外,你需要在view里在form里增加下面代码: 8 *<input type="hidden" name="token" value="${token}"> 9  * 此时会在拦截器中验证是否重复提交10  * </p>11  *12  */13 import java.lang.annotation.*;14 15 @Target(ElementType.METHOD)16 @Retention (RetentionPolicy.RUNTIME)17 public @interface Token {18  19      boolean save() default false ;20  21      boolean remove() default false ;22 }

 

2,自定义一个针对该注解的拦截器 TokenInterceptor 

 1 package com.bjca.framework.util; 2  3 import org.apache.commons.logging.Log; 4 import org.apache.commons.logging.LogFactory; 5 import org.springframework.web.method.HandlerMethod; 6 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 7  8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse;10 import java.lang.reflect.Method;11 import java.util.UUID;12 13 public class TokenInterceptor extends HandlerInterceptorAdapter {14     public static Log log = LogFactory.getLog(TokenInterceptor.class);15      @Override16      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {17           System.out.println(handler.getClass());18          if (handler instanceof HandlerMethod) {19              HandlerMethod handlerMethod = (HandlerMethod) handler;20              Method method = handlerMethod.getMethod();21              Token annotation = method.getAnnotation(Token. class );22            23              if (annotation != null ) {24                  boolean needSaveSession = annotation.save();25                  if (needSaveSession) {26                      String uuid=UUID.randomUUID().toString();27                         log.debug("提交生成除令牌"+uuid);28                      request.getSession( false ).setAttribute( "token" , uuid);29                  }30                  boolean needRemoveSession = annotation.remove();31                  if (needRemoveSession) {32                      if (isRepeatSubmit(request)) {33                          return false ;34                      }35                      log.debug("提交移除令牌"+request.getSession().getAttribute("token" ));36                      request.getSession( false ).removeAttribute( "token" );37                  }38              }39              return true ;40          } else {41              return super .preHandle(request, response, handler);42          }43      }44  45      private boolean isRepeatSubmit(HttpServletRequest request) {46          String serverToken = (String) request.getSession( false ).getAttribute( "token" );47          if (serverToken == null ) {48              return true ;49          }50          String clinetToken = request.getParameter( "token" );51          if (clinetToken == null ) {52              return true ;53          }54          if (!serverToken.equals(clinetToken)) {55              return true ;56          }57          return false ;58      }59 }

3,在spring MVC的配置文件里注册该拦截器

 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3     xmlns:mvc="http://www.springframework.org/schema/mvc"  4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5     xmlns:p="http://www.springframework.org/schema/p"  6     xmlns:context="http://www.springframework.org/schema/context" 7     xsi:schemaLocation="http://www.springframework.org/schema/beans  8         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  9         http://www.springframework.org/schema/context 10         http://www.springframework.org/schema/context/spring-context-4.0.xsd 11         http://www.springframework.org/schema/mvc 12         http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"13     >14     <!-- 对spring org.lxh包下所有注解扫描 -->15     <context:component-scan base-package="com.xxx">16         <context:exclude-filter type="annotation"  expression="org.springframework.stereotype.Repository" />17     </context:component-scan>20     <!-- 支持spring mvc新的注解类型 详细spring3.0手册 15.12.1 mvc:annotation-driven-->21     <mvc:annotation-driven />22     23     <bean  id="viewResolver"24             class="org.springframework.web.servlet.view.InternalResourceViewResolver">25             <!-- 为了使用JSTL Tag修改默认的viewClass属性 -->26             <property27                   name="viewClass"28                   value="org.springframework.web.servlet.view.JstlView" />29             <property30                   name="prefix"31                   value="/WEB-INF/views/" />32             <property33                   name="suffix"34                   value=".jsp"></property>35             <property36                   name="order"37                   value="1"></property>38         </bean>39    <!-- 拦截器 -->40     <mvc:interceptors>41        <!-- 用户登录拦截 -->42         <bean class="com.xx.xxx.filter.StageSecurityInterceptor">43             <property name="patterns" >44                 <list>45                     <value>.*/console/.*\.jhtml</value>46                     <value>.*/center/.*\.jhtml</value>47                   48                 </list>49             </property>50             <property name="loginView">51                 <value>/manage.jsp</value>52             </property>53         </bean>54          <!-- 配置Token拦截器,防止用户重复提交数据 -->55         <mvc:interceptor>56             <mvc:mapping path="/**"/>57             <bean class="com.xxx.framework.util.TokenInterceptor"/>58         </mvc:interceptor>59     </mvc:interceptors>60     <!--  61      <bean id="viewResolver"62           class="org.springframework.web.servlet.view.ResourceBundleViewResolver">63         <property name="basenames">64             <list>65                 <value>views-stage</value>66             </list>67         </property>68     </bean>69     -->70 </beans>

 4,演示demo

4.1,在跳转至某个需要加上@Token(save = true)

1     @RequestMapping("/personalForm.jhtml")2   @Token(save = true)3     public String personalForm(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {4         Account account = Account.sessionAccount();5         if (account == null) {6             return "redirect:/login.jsp";7         }8       //..........业务..............9   }    

 

 4.2,在上个Controller 跳转的方法上加入${Token} 

 1 <div class="main clearfix nav center regist copyright_main5"> 2         <h3 class="registTitle">填写身份信息</h3> 3         <img alt="" src="<c:url value='/platform/stage/image/regist/wave.png'/>"><br /> <img src="<c:url value='/platform/stage/image/portals/regist-info.png'/>"></img> 4         <c:if test="${personalInfoForm.checkState eq 2}"> 5         <br/> 6         <div> 7         <font color="red" size="2"><span>身份认证意见:${personalInfoForm.checkOpnion}</span></font> 8         </div> 9         </c:if>10         <form autocomplete="off" style="margin: 0;" id="form1" method="post" name="personalInfoForm" action="<c:url value='/center/member/savePersonalInfo.jhtml'/>" enctype="multipart/form-data">11             <input type="hidden" value="${personalInfoForm.id}" name="id" />12             <input type="hidden" name="token" value="${token}">             

 4.3,在表单提交方法的地方加上注解 @Token(remove = true)

 1 @RequestMapping(value = "/savePersonalInfo.jhtml", method = {RequestMethod.POST}) 2     @Token(remove = true) 3     public String savePersonalInfo(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap, PersonalInfo personalInfoForm) throws Exception { 4         DateFormat fm = new SimpleDateFormat("yyyy-MM-dd"); 5         Date birthday = fm.parse(request.getParameter("birthday2")); 6         personalInfoForm.setBirthday(birthday); 7        8         Account account = Account.sessionAccount(); 9         if(account==null){10             return "redirect:/login.jsp";11         }12     //.....................业务.........................13 }    

 5,完成了。

原创粉丝点击