一、思路
用户每次发送请求都有一个标记,这个标记设置成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 {
@Autowired
private 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 {
@Resource
RedisTemplate<String, String> redisTemplate;
public String login(String phone, String password, HttpServletResponse response){
//签名密钥
String signature = "hello";
JwtBuilder builder = Jwts.builder();
//使用JWT生成器创建一个JWT
String jwtToken = builder
//Header
.setHeaderParam("typ", "JWT")
//类型
.setHeaderParam("alg", "HS256")
//使用的算法
//Payload
.claim("phone", phone)
.setSubject("admin-test")
.setExpiration(new Date(System.currentTimeMillis() + 10006060*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 "登录成功!!";
}
}