1. 程式人生 > >SpringMVC後臺token防重複提交解決方案

SpringMVC後臺token防重複提交解決方案

本文介紹如何使用token來防止前端重複提交的問題。


目錄

  • 1.思路
  • 2.攔截器原始碼實現
  • 3.註解原始碼
  • 4.攔截器的配置
  • 5.使用指南
  • 6.結語

思路

1.新增攔截器,攔截需要防重複提交的請求
2.通過註解@Token來新增token/移除token
3.前端頁面表單新增(如果是Ajax請求則需要在請求的json資料中新增token值)

核心原始碼

攔截器原始碼實現

/**
 * com.xxx.interceptor.TokenInterceptor.java
 * Copyright 2018 Lifangyu, Inc. All rights reserved.
 */
package com.xxx.common.interceptor; import org.apache.log4j.Logger; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import
java.util.Random; import java.util.UUID; /** * Desc:防重複提交的攔截器 * <p> * Created by lifangyu on 2018/02/27. */ public class TokenInterceptor extends HandlerInterceptorAdapter { Logger logger = Logger.getLogger(TokenInterceptor.class); static String splitFlag = "_"; @Override public
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{ if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); Token annotation = method.getAnnotation(Token.class); if (annotation != null) { boolean needSaveSession = annotation.add(); if (needSaveSession) { Random random = new Random(); String uuid = UUID.randomUUID().toString().replace(splitFlag, String.valueOf(random.nextInt(100000))); String tokenValue = String.valueOf(System.currentTimeMillis()); request.setAttribute("token", uuid + splitFlag + tokenValue); // session 中 token 的key 每次都是變化的[適應瀏覽器 開啟多個帶有token的頁面不會有覆蓋session的key] request.getSession(true).setAttribute(uuid, tokenValue); } boolean needRemoveSession = annotation.remove(); if (needRemoveSession) { if (isRepeatSubmit(request)) { logger.warn("please don't repeat submit,url:" + request.getServletPath()); return false; } String clinetToken = request.getParameter("token"); if (clinetToken != null && clinetToken.indexOf(splitFlag) > -1) { request.getSession(true).removeAttribute(clinetToken.split("_")[0]); } } } return true; } else { return super.preHandle(request, response, handler); } } /** * 判斷是否是重複提交 * * @param request * @return */ private boolean isRepeatSubmit(HttpServletRequest request) { String clinetToken = request.getParameter("token"); if (clinetToken == null) { return true; } if (clinetToken.indexOf(splitFlag) > -1) { String uuid = clinetToken.split("_")[0]; String token = clinetToken.split("_")[1]; String serverToken = (String) request.getSession(true).getAttribute(uuid); if (serverToken == null) { return true; } if (!serverToken.equals(token)) { return true; } } return false; } } 複製程式碼

註解原始碼

/**
 * com.xxx.interceptor.Token.java
 * Copyright 2018 Lifangyu, Inc. All rights reserved.
 */
package com.xxx.common.interceptor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Desc:Token 註解
 * <p>
 * Created by lifangyu on 2018/02/27.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Token {

    /**
     * 新增token的開關[true:新增;false:不新增,default:false]
     *
     * @return
     */
    boolean add() default false;

    /**
     * 移除token的開關[true:刪除;false:不刪除,default:false]
     *
     * @return
     */
    boolean remove() default false;

}
複製程式碼

攔截器的配置

在springMVC的servlet配置檔案中配置攔截器

<!-- 攔截器配置 -->
<mvc:interceptors>
	<!-- 配置Token攔截器,防止使用者重複提交資料 -->
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="com.xxx.interceptor.TokenInterceptor"/>
	</mvc:interceptor>
</mvc:interceptors>
複製程式碼

使用指南

1.在進入頁面的controller方法上添加註解@Token(add=true)

@Token(add = true)
@RequestMapping("toXxxHtml")
public String toXxxHtml(Model mv) {
   ......
   return "xxx/xxxHtml";
}
複製程式碼

2.在頁面toXxxHtml.html新增

<form id="xxx_submit_form" class="form-horizontal" action="${ctx}/xxx/addXxx.do" method="post">
   ......
   <!-- 注:name必須是token -->
   <input type="hidden"  name="token" value="${token!''}"/>
   ......
</form>
複製程式碼

3.在防止重複提交的controller方法上新增@Token(remove = true)

@Token(remove = true)
@RequestMapping("addXxx")
public String addXxx() throws Exception {
   ......
   return "redirect:toXxxHtml.do";
}
複製程式碼

結語

到此本文就結束了,歡迎大家繼續關注更多Spring案例。

掃描下面二維碼,關注我的公眾號哦!!!


關注我的公眾號