一、思路
用户每次发送请求都有一个标记,这个标记设置成5s有效存到redis中。每次请求检查该标记是否有效,还有效就说明请求太频繁了。无效就说明请求之间时间间隔够了,可以继续请求了。
gitee地址:添加链接描述
二、实现
- 自定义注解
import java.lang.annotation.*;
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {int lockTime() default 5;
}
- 注解+aop前置通知检查redis。将请求路径和当前用户token拼接存到redis中,并设置过期时间
import com.qcby.aop_cftj.myannotation.NoRepeatSubmit;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.concurrent.TimeUnit;@Component
@Aspect
public class NoRepeatSubmitAspect {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Pointcut("@annotation(repeatSubmit)")public void pointcutNoRepeat(NoRepeatSubmit repeatSubmit){};@Around("pointcutNoRepeat(noRepeatSubmit)")public Object doNoRepeat(ProceedingJoinPoint point, NoRepeatSubmit noRepeatSubmit) throws Throwable {int i=noRepeatSubmit.lockTime();HttpServletRequest httpServletRequest = HttpServletRequest();Cookie[] cookies = httpServletRequest.getCookies();String token="";if(cookies!=null){for (Cookie cookie : cookies) {if(cookie.getName().equals("token")){token=cookie.getValue().toString();}}}String url = httpServletRequest.getRequestURL().toString();String sign = url+"/"+token;Boolean key=redisTemplate.hasKey(sign);if (key){System.out.println("请勿重复提交!!");return null;
// throw new Exception("请勿重复提交");}redisTemplate.opsForValue().set(sign,sign,i, TimeUnit.SECONDS);return point.proceed();}public static HttpServletRequest HttpServletRequest(){return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();}
- 请求时根据用户信息生成token并存到cookie中
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.UUID;
@Service
public class LoginService {@ResourceRedisTemplate<String, String> redisTemplate;public String login(String phone, String password, HttpServletResponse response){//签名密钥String signature = "hello";JwtBuilder builder = Jwts.builder();//使用JWT生成器创建一个JWTString jwtToken = builder//Header.setHeaderParam("typ", "JWT")//类型.setHeaderParam("alg", "HS256")//使用的算法//Payload.claim("phone", phone).setSubject("admin-test").setExpiration(new Date(System.currentTimeMillis() + 1000*60*60*24))//失效日期:当前时间+24小时.setId(UUID.randomUUID().toString())//signature.signWith(SignatureAlgorithm.HS256, signature)//使用的算法+签名密钥//调用compact()方法将三部分拼接起来并用'.'分隔.compact();Cookie cookie=new Cookie("token",jwtToken.substring(0,5));response.addCookie(cookie);return "登录成功!!";}
}