生产环境下可以解决的问题:

  1.短信验证码请求评率限制(防止抓包短信轰炸)

  2.热点数据请求评率限制(防止数据库爆炸)

  

1.创建自定义注解

package com.bysk.base.annotation;

import java.lang.annotation.*;

/**
* @author: zhangyb
* @date:  2020/11/11 13:58
* @Description: 防止表单重复提交 使用这个注解必须要返回Result类型
* @UpdateUser : zhangyb
* @UpdateDate :2020/11/11 13:58
* @UpdateRemark:
*/
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FormSubmitLimit {
    /**
    * @author: zhangyb
    * @date:  2020/11/11 14:00
    * @Description: 默认两秒
    * @UpdateUser : zhangyb
    * @UpdateDate :2020/11/11 14:00
    * @UpdateRemark:
    */
    long limitTime() default 2L;
    /**
    * @author: zhangyb
    * @date:  2020/11/11 14:03
    * @Description: 是否需要登录,默认需要登录
    * @UpdateUser : zhangyb
    * @UpdateDate :2020/11/11 14:03
    * @UpdateRemark:
    */
    boolean isLogin() default true;
}
View Code

2.AOP实现之定义注解

package com.bysk.admin.common.filter;

import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSONObject;
import com.bysk.base.annotation.FormSubmitLimit;
import com.bysk.base.enums.MsgEnum;
import com.bysk.base.model.Result;
import com.bysk.base.util.MD5Utils;
import com.bysk.base.util.RedisUtils;
import com.bysk.base.util.WebUtils;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author: zhangyb
 * @date:  2020/11/11 14:02
 * @Description: 防止表单重复提交的请求 使用此注解返回类型必须是R    Result
 * @UpdateUser : zhangyb
 * @UpdateDate :2020/11/11 14:02
 * @UpdateRemark:
 */
@Aspect
@Component
public class FormSubmitAspect {
    @Autowired
    RedisUtils redisUtils;
    @Around("@annotation(formSubmitLimit)")
    @SneakyThrows
    public Object doBefore(ProceedingJoinPoint point, FormSubmitLimit formSubmitLimit) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String requestURI = request.getRequestURI();
        if (formSubmitLimit.isLogin()){
            //如果需要登录redis存储规则 userid<->请求url_method
            Object o = redisUtils.get(WebUtils.getUser().getId() + "");
            if (o!=null){
                return JSONObject.toJSONString(Result.fail(MsgEnum.OPR_FAST));
            }
            try {
                redisUtils.set(WebUtils.getUser().getId()+"",requestURI,formSubmitLimit.limitTime());
            } catch (NullPointerException e) {
                return Result.fail();
            }
        }else{
            //客户端IP
            String clientIP = ServletUtil.getClientIP(request);
            //客户端请求头的userAgent
            String header = request.getHeader("User-Agent");
            //MD5加密后的值
            String noLoignKey = MD5Utils.encryptBasedDes(clientIP + header);
            Object o = redisUtils.get(noLoignKey);
            if (o!=null){
                return Result.fail(MsgEnum.OPR_FAST);
            }
            //不需要登录redis存储规则 ip+user_agent(MD5)<-> 请求url_mthod
            redisUtils.set(noLoignKey,requestURI,formSubmitLimit.limitTime());
        }
        return  point.proceed();
    }
}
View Code