复述,实现登陆次数限制的思路详解

  


  

  

利用复述,实现登陆次数限制,注解+ aop,核心代码很简单。

  

  

比如希望达到的要求是这样:在1分钟内登陆异常次数达到5次,锁定该用户1 h

  

那么登陆请求的参数中,会有一个参数唯一标识一个用户,比如邮箱/手机号/用户名

  

用这个参数作为关键存入复述,对应的价值为登陆错误的次数、字符串类型,并设置过期时间为1分钟。当获取到的值=https://www.yisu.com/zixun/=?”,说明当前请求为第5次登陆异常,锁定。

  

所谓的锁定,就是将对应的值设置为某个标识符,比如“锁”,并设置过期时间为1 h

  

  

定义一个注解,用来标识需要登陆次数校验的方法

        包io.github.xiaoyureed.redispractice.anno;   进口java.lang.annotation。*;   @Documented   @Target ({ElementType.METHOD})   @Retention (RetentionPolicy.RUNTIME)   公共@ interface RedisLimit {/* *   *标识参数名,必须是请求参数中的一个   */字符串标识符();/* *   *在多长时间内监控,如希望在60年代内尝试   *次数限制为5次,那么看=60;单位:年代   */长时间看();/* *   *锁定时长,单位:s   */长锁();/* *   *错误的尝试次数   */int * ();   }      

编写切面,在目标方法前后进行校验,处理…

        包io.github.xiaoyureed.redispractice.aop;   @ component   @Aspect//确保当前的建议是比ControllerAOP外//我们可以处理异常登录限制在这个aop的建议。//@Order (9)   @Slf4j   公开课RedisLimitAOP {   @ autowired   私人StringRedisTemplate StringRedisTemplate;   @Around (“@annotation (io.github.xiaoyureed.redispractice.anno.RedisLimit)”)   公共对象handleLimit (ProceedingJoinPoint连接点){   MethodSignature MethodSignature=(MethodSignature) joinPoint.getSignature ();   最后的方法方法=methodSignature.getMethod ();   最后RedisLimit redisLimitAnno=method.getAnnotation (RedisLimit.class);//貌似可以直接在方法参数中注入todo   最终字符串标识符=redisLimitAnno.identifier ();   最后长看=redisLimitAnno.watch ();   最后一个int *=redisLimitAnno.times ();   最后长锁=redisLimitAnno.lock ();//最后ServletRequestAttributes att=(ServletRequestAttributes) RequestContextHolder.currentRequestAttributes ();//最后HttpServletRequest请求=att.getRequest ();//最后一个字符串identifierValue=https://www.yisu.com/zixun/request.getParameter(标识符);   字符串identifierValue=零;   尝试{   最终对象参数=joinPoint.getArgs () [0];   最后一场declaredField=arg.getClass () .getDeclaredField(标识符);   declaredField.setAccessible(真正的);   identifierValue=(字符串)declaredField.get (arg);   }捕捉(NoSuchFieldException e) {   log.error(“祝辞祝辞祝辞无效的标识符({}),找不到这个领域在请求参数”,标识符);   }捕捉(IllegalAccessException e) {   e.printStackTrace ();   }   如果(StringUtils.isBlank (identifierValue)) {   log.error(“祝辞祝辞祝辞RedisLimit的价值。标识符不能空白,无效的标识符:{}”,标识符);   }//检查用户锁定   最后ValueOperations<字符串,String>ssop=stringRedisTemplate.opsForValue ();   最终字符串国旗=ssOps.get (identifierValue);   如果(国旗!=零,,“锁”.contentEquals(国旗)){   最后BaseResp结果=new BaseResp ();   结果。setErrMsg(“用户锁定”);   result.setCode (" 1 ");   返回新ResponseEntity<祝辞(因此,HttpStatus.OK);   }   ResponseEntity结果;   尝试{   结果=(ResponseEntity) joinPoint.proceed ();   }捕捉(Throwable e) {   结果=handleLoginException (e, identifierValue,手表,时间,锁);   }   返回结果;   }   私人ResponseEntity handleLoginException (Throwable e弦identifierValue,长期看,int,长锁){   最后BaseResp结果=new BaseResp ();   result.setCode (" 1 ");   如果(e instanceof LoginException) {   log.info(“祝辞祝辞祝辞处理登录异常…”);   最后ValueOperations<字符串,String>ssop=stringRedisTemplate.opsForValue ();   布尔存在=stringRedisTemplate.hasKey (identifierValue);//键不存在,所以它是世界上第一个登录失败   如果存在(==null | | !存在){   ssop。集(identifierValue,“1”,看,TimeUnit.SECONDS);   result.setErrMsg (e.getMessage ());   返回新ResponseEntity<祝辞(因此,HttpStatus.OK);   }   字符串数=ssOps.get (identifierValue);//已达到限制   如果(Integer.parseInt (count) + 1==*) {   log.info(“祝辞祝辞祝辞({})已经达到限制和将被锁定为{}年代”,identifierValue,锁);   ssop。集(identifierValue,“锁”锁,TimeUnit.SECONDS);   结果。setErrMsg(“用户锁定”);   返回新ResponseEntity

复述,实现登陆次数限制的思路详解