【分享】表单重复提交后端限制

在首页看到基于前段并行控制的表单重复提交限制,觉得不用那么复杂,再此献上后端限制代码

1)注解类

package plus.jfinal.annotations;

import java.lang.annotation.*;

/**
 * 重复提交Token
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DuplicateSubmitToken {
    /**
     * 3s 超时
     * @return
     */
    long limit() default 3000;
}

2)拦截器

package plus.jfinal.core.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import plus.jfinal.annotations.DuplicateSubmitToken;
import plus.jfinal.entitys.Result;

public class DuplicateSubmitInterceptor implements Interceptor {

    @Override
    public void intercept(Invocation inv) {

        DuplicateSubmitToken token = inv.getMethod().getAnnotation(DuplicateSubmitToken.class);
        Controller controller = inv.getController();
        String key = "token;"+inv.getActionKey();
        if(token!=null){
            Object t = controller.getSession().getAttribute(key);
            if(t == null){
                controller.getSession().setAttribute(key,System.currentTimeMillis());
            }else{
                long time = Long.parseLong(t.toString());
                long surplus = System.currentTimeMillis()-time;
                if(surplus > token.limit()){
                    controller.getSession().setAttribute(key,System.currentTimeMillis());
                }else{
                    controller.renderJson(new Result().setFail(430, String.format("禁止重复提交,两次提交时间间隔( %s 秒 ),还需等待 %s 秒", token.limit()/1000,(token.limit()-surplus)/1000)));
                    return ;
                }
            }
        }
        inv.invoke();
        if(token!=null){
            controller.getSession().setAttribute(key,System.currentTimeMillis());
        }
    }
}

使用方式:

# JFinalConfig 添加

public void configInterceptor(Interceptors me) {
    me.add(new DuplicateSubmitInterceptor());
    ...
}

# 具体控制层添加
@DuplicateSubmitToken
public void index(){
    ...
}

打完收枪~

评论区

JFinal

2020-02-15 13:52

拦截器实现重复提交验证的方式比较新颖,博主具有创新精神,赞

何足道

2020-03-14 13:30

key再把request里面传的数据加上,以区分是重复提交了还是新请求

Psbye

2020-03-16 22:29

@何足道 key 没有加上 request 的参数,key 是加上 当前请求的 action ,来标识是唯一的action 用于对此类action进行判断

zzutligang

2020-04-06 10:01

@Psbye 这个拦截器能不能不在全局注册,在需要的地方直接@Before(DuplicateSubmitInterceptor.class),然后再写上@DuplicateSubmitToken?

Psbye

2020-04-06 19:07

@zzutligang 你说的这个我没尝试过,不过你的想法有意思,能尽量减少一层拦截器链,你可以尝试一下,理论按照jfinal的机制是可以的

zzutligang

2020-04-07 10:50

@Psbye 实际测试,完全可以。另外我把你这个拦截器扩展了一下,适合分布式部署。

Psbye

2020-04-07 16:34

@zzutligang 欢迎扩展,若可以也分享出来,让大家都受用哈

ThreeX

2020-04-23 14:54

jmeter 测试,发起4个请求。2个请求立即成功,另两个请求等limit设置的时间到后也成功。这方法似乎不起作用

Psbye

2020-04-23 22:33

@ThreeX 还真没进行压力测试过,另两个请求等limit设置的时间到后也成功这个应该是正常的吧 限制时间到后就可以继续添加了 感谢提供测试结论