持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
前言
前几天去长沙玩了,凌晨的解放西路属实是给我震惊了。这周回来这几天也解决了两个小小的需求,浅浅记录总结一下吧!今天先写一个登陆限制相关的内容吧!
背景
项目马上验收了,安全性评估中提到了登录验证的问题,之前没有做任何限制;为了防止暴力破解的情况,现在对登录增加限制条件:两分钟内连续登录失败三次,限制登录五分钟;
领导说不用太复杂,用redis简单实现就行;
思路
因为原有的登录是用到了aouth服务,用到了token;那就在此基础上进行改动:
redis里设置两个key,一个用来记录登录失败次数,一个用来记录限制登录状态;建议key中拼接上当前登录的用户名;
- 1.登录前先检查账号是否处于限制登录状态
- 2.登录时记录登录失败次数
- 3.成功登录后清除登录失败的记录
用到的redis相关方法
redis里目录层级可以用 : 来设置,如:
String keyLoginFail="tsp:loginCheck:"+userName+": login:fail:count";//用户登录失败次数
- 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的接口的返回值处理中,加入了登录时记录登录失败次数 接口以及 成功登录后清除登录失败的记录接口;
总结
以上就是整个过程,之前很久都没有处理过这些逻辑性的东西了,这次上手就感觉陌生了不少;但是写代码的魅力就在这,一步一步的向着自己的目标去努力,最终达到想要的结果,那个时候可是很有成就感的哟~