返回博客列表web
原 Spring MVC攔截器+註解方式實現防止表單重複提交spring
mushui服務器
原理:在新建頁面中Session保存token隨機碼,當保存時驗證,經過後刪除,當再次點擊保存時因爲服務器端的Session中已經不存在了,全部沒法驗證經過。mvc
1.新建註解:app
/** * <p> * 防止重複提交註解,用於方法上<br/> * 在新建頁面方法上,設置needSaveToken()爲true,此時攔截器會在Session中保存一個token, * 同時須要在新建的頁面中添加 * <input type="hidden" name="token" value="${token}"> * <br/> * 保存方法須要驗證重複提交的,設置needRemoveToken爲true * 此時會在攔截器中驗證是否重複提交 * </p> * @author: chuanli * @date: 2013-6-27上午11:14:02 * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AvoidDuplicateSubmission { boolean needSaveToken() default false; boolean needRemoveToken() default false; }
2. 新建攔截器ide
/** * <p> * 防止重複提交過濾器 * </p> * * @author: chuanli * @date: 2013-6-27上午11:19:05 */ public class AvoidDuplicateSubmissionInterceptor extends HandlerInterceptorAdapter { private static final Logger LOG = Logger.getLogger(AvoidDuplicateSubmissionInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { User user = UserUtil.getUser(); if (user != null) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); AvoidDuplicateSubmission annotation = method.getAnnotation(AvoidDuplicateSubmission.class); if (annotation != null) { boolean needSaveSession = annotation.needSaveToken(); if (needSaveSession) { request.getSession(false).setAttribute("token", TokenProcessor.getInstance().generateToken()); } boolean needRemoveSession = annotation.needRemoveToken(); if (needRemoveSession) { if (isRepeatSubmit(request)) { LOG.warn("please don't repeat submit,[user:" + user.getUsername() + ",url:" + request.getServletPath() + "]"); return false; } request.getSession(false).removeAttribute("token"); } } } return true; } private boolean isRepeatSubmit(HttpServletRequest request) { String serverToken = (String) request.getSession(false).getAttribute("token"); if (serverToken == null) { return true; } String clinetToken = request.getParameter("token"); if (clinetToken == null) { return true; } if (!serverToken.equals(clinetToken)) { return true; } return false; } }
3. 在Spring中配置ui
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="interceptors"> <list> <bean class="com.sohu.tv.crm.aop.UserLogInterceptor"/> <bean class="com.sohu.tv.crm.aop.AvoidDuplicateSubmissionInterceptor"/> </list> </property> </bean>
4. 在相關方法中加入註解:url
@RequestMapping("/save") @AvoidDuplicateSubmission(needRemoveToken = true) public synchronized ModelAndView save(ExecutionUnit unit, HttpServletRequest request, HttpServletResponse response) throws Exception { @RequestMapping("/edit") @AvoidDuplicateSubmission(needSaveToken = true) public ModelAndView edit(Integer id, HttpServletRequest request) throws Exception {
5.在新建頁面中加入.net
<input type="hidden" name="token" value="${token}">code