This article describes how to use tokens to prevent the problem of repeated submissions in the front end.


directory

  • 1. The train of thought
  • 2 interceptor source code implementation
  • 3. Annotate source code
  • 4. Configuration of interceptors
  • 5. Usage Guide
  • 6. Conclusion

Train of thought

Add an interceptor to block requests that need to prevent repeated submissions. 2. Annotate @token to add/remove tokens 3. Front-end page form addition (add token value to request JSON data if Ajax request)

The core source

Interceptor source code implementation

/** * 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;

/** * 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) {
                return true;
            }
            
            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);
                // The token key in the session is changed every time [adapt to browser opening multiple pages with tokens without overwriting the 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); }}/** * check if the submission is repeated@param request
     * @return* /
    private boolean isRepeatSubmit(HttpServletRequest request) {

        String clinetToken = request.getParameter("token");

        if (clinetToken == null) {
            return true;
        }
        if (clinetToken.indexOf(splitFlag) <= -1) {
            return false;
        }
        
        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; }}Copy the code

Annotated source

/** * 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;

/** * Created by lifangyu on 2018/02/27. */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Token {

    /** * Add token switch [true: add; false: not add; default: false] **@return* /
    boolean add(a) default false;

    /** * Remove token switch [true: delete; false: do not delete; default: false] **@return* /
    boolean remove(a) default false;

}
Copy the code

Configuration of interceptors

Configure interceptors in the Servlet configuration file of springMVC

<! Interceptor configuration -->
<mvc:interceptors>
	<! -- Configure Token interceptor to prevent users from submitting data repeatedly -->
	<mvc:interceptor>
		<mvc:mapping path="/ * *"/>
		<bean class="com.xxx.interceptor.TokenInterceptor"/>
	</mvc:interceptor>
</mvc:interceptors>
Copy the code

Use guide

1. Add annotation @token (add=true) to the controller method that enters the page

@Token(add = true)
@RequestMapping("toXxxHtml")
public String toXxxHtml(Model mv) {...return "xxx/xxxHtml";
}
Copy the code

2. Add in toxxxhtml.html

<form id="xxx_submit_form" class="form-horizontal" action="${ctx}/xxx/addXxx.do" method="post">.<! Note: name must be token -->
   <input type="hidden"  name="token" value="${token! "'}"/>.</form>
Copy the code

3. Add @token (remove = true) to controller method to prevent double commits

@Token(remove = true)
@RequestMapping("addXxx")
public String addXxx(a) throws Exception {...return "redirect:toXxxHtml.do";
}
Copy the code

conclusion

This concludes the article, and you are welcome to stay tuned for more Spring examples.

Scan the qr code below and follow my official account!!