两分钟内连续登录失败三次,限制登录五分钟

491 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情

前言

前几天去长沙玩了,凌晨的解放西路属实是给我震惊了。这周回来这几天也解决了两个小小的需求,浅浅记录总结一下吧!今天先写一个登陆限制相关的内容吧!

背景

项目马上验收了,安全性评估中提到了登录验证的问题,之前没有做任何限制;为了防止暴力破解的情况,现在对登录增加限制条件:两分钟内连续登录失败三次,限制登录五分钟;

领导说不用太复杂,用redis简单实现就行;

思路

因为原有的登录是用到了aouth服务,用到了token;那就在此基础上进行改动:

redis里设置两个key,一个用来记录登录失败次数,一个用来记录限制登录状态;建议key中拼接上当前登录的用户名;

  • 1.登录前先检查账号是否处于限制登录状态
  • 2.登录时记录登录失败次数
  • 3.成功登录后清除登录失败的记录

用到的redis相关方法

redis里目录层级可以用 来设置,如:

String keyLoginFail="tsp:loginCheck:"+userName+": login:fail:count";//用户登录失败次数

image.png

  • redisTemplate.hasKey() 判断相应的key是否存在
  • redisTemplate.getExpire() 获取相应key的过期时间
  • redisTemplate.opsForValue().set() 设置相应key的值
  • redisTemplate.expire() 设置相应key的过期时间
  • redisTemplate.opsForValue().get() 获取相应key的值
  • redisTemplate.opsForValue().increment() 给相应key的值自增1

登录前先检查账号是否处于限制登录状态

编写相应接口,用来查询当前登录的用户名是否处于限制登录状态,即:

String keyLoginStop="tsp:loginCheck:"+userName+": login:stop:time";//用户禁止登录时间
if (redisTemplate.hasKey(keyLoginStop)){
   long stopTime=redisTemplate.getExpire(keyLoginStop, TimeUnit.MINUTES);//剩余 禁止登陆时间
   return  R.data("帐号处于限制登录状态,请在"+stopTime+"分钟后重新登录");
}else{
   return R.data("正常登录");
}

登录时记录登录失败次数

编写相应接口,用来记录当前登录的用户名的失败次数;

首次失败时需要给记录次数的key赋值,也要设置其有两分钟的过期时间;

redisTemplate.opsForValue().set(keyLoginFail,"1");
redisTemplate.expire(keyLoginFail,2,TimeUnit.MINUTES);

非首次失败,要判断失败次数是否超过限定次数;

超过则设置限制登陆的key有5分钟的过期时间,同时给其赋值;

否则,就将记录失败次数的key的值自增1;

int failCount=Integer.parseInt(redisTemplate.opsForValue().get(keyLoginFail));
if (failCount>=num-1){
   //超过限制次数,冻结帐号
   redisTemplate.opsForValue().set(keyLoginStop,"1");
   redisTemplate.expire(keyLoginStop,5,TimeUnit.MINUTES);
   return  R.data("用户名或密码输入错误超过三次,限制登录五分钟");
}else {
   redisTemplate.opsForValue().increment(keyLoginFail,1);
   return R.data("用户名或密码输入错误"+(failCount+1)+"次,在2分钟内还可输入"+(num-(failCount+1))+"次");
}

成功登录后清除登录失败的记录

编写接口,在成功登录后清除登录失败的记录;

这个一开始并没有想到,后来在自己测试的时候发现,失败两次后成功一次再失败一次,账户就限制登录了,这可不行呀!于是就又补上了这个接口;

实现很简单,就是redis有相应的key直接delete就行了;

if (redisTemplate.hasKey(keyLoginFail)){
   redisTemplate.delete(keyLoginFail);
   return  R.data("清除登录失败记录缓存成功");
}else{
   return R.data("无登录失败记录");
}

前端做相应处理

项目前端使用了vue,对axios进行了统一封装;这次改动就把state为400且错误信息为“用户名或密码错误”这个做了单独处理,具体情况还是要具体分析的哟~

然后在具体的接口调用上也做了调整,原来只有一个获取token的接口,现在把它放在了登录前先检查账号是否处于限制登录状态 接口返回值的处理中,在获取token的接口的返回值处理中,加入了登录时记录登录失败次数 接口以及 成功登录后清除登录失败的记录接口;

总结

以上就是整个过程,之前很久都没有处理过这些逻辑性的东西了,这次上手就感觉陌生了不少;但是写代码的魅力就在这,一步一步的向着自己的目标去努力,最终达到想要的结果,那个时候可是很有成就感的哟~