利用Redis实现统计登录失败次数,限制登陆
登录失败需要统计失败次数,达到一定次数需要等待一段时间才能尝试再次登录。本文利用redis实现此功能
一、基础的登录功能
SystemController
@PostMapping("/adminLogin")
public Result adminLogin(@RequestParam(value = "username") String username, @RequestParam(value = "password") String password,
@RequestParam(value = "imageCode") String imageCode,HttpServletRequest request){
//判断是否为账号密码是否为空——也可以通过@Valid 设置不能为空
if (StringUtils.isBlank(username)){
Result.error("用户名不能为空");
}else if (StringUtils.isBlank(password)){
Result.error("密码不能为空");
}
String ip =HttpUtil.getIpAddr(request);
if (StringUtils.isBlank(imageCode)){
return Result.error("验证码不能为空");
}
if (!codeManager.verifycode(ip,imageCode)){
return Result.error("验证码不正确");
}
//根据用户名找角色
Admin admin = adminService.getOne(new LambdaQueryWrapper<Admin>().eq(Admin::getUsername,username));
if (admin==null){
Result.error("用户名或者密码错误");
}else {
passwordCheckManager.checkPassword(admin.getUsername(),password,admin.getPassword(),Admin_Role);
}
SysUser sysUser = new SysUser();
sysUser.setId(admin.getId());
sysUser.setUsername(admin.getUsername());
sysUser.setRole(Admin_Role);
LoginVo loginVo = tokenManager.getToken(sysUser);
Map data = new HashMap<>();
data.put("LoginVo",loginVo);
return Result.ok("登录成功",data);
}
基本的登录接口,根据username去利用mybatis去获取对应的用户信息
若获取到信息则调用passwordCheckManger中的checkPassword方法,
若没有获取到信息,则提示用户名密码错误(找不到对应的信息)
PasswordCheckManger
@Component
public class PasswordCheckManager {
@Autowired
private RedisTemplate redisTemplate;
private static final int LOGIN_ERRO_MAX = 5;
private static final String CHECK_VALID_CODE_NUM_PREFIX = "checkerpassworderror:";
public void checkPassword(String username,String password,String enpassword,String role){
String checkPrefix= CHECK_VALID_CODE_NUM_PREFIX+role+"_";
int count = 0;
if (redisTemplate.hasKey(checkPrefix+username)){
count = Integer.valueOf(redisTemplate.opsForValue().get(checkPrefix+username).toString());
}
if (count > LOGIN_ERRO_MAX){
throw new GuliException("密码输错5次,请30分钟后尝试");
}
//半小时后失效
redisTemplate.opsForValue().set(checkPrefix+username,count,30, TimeUnit.MINUTES);
//密码不正确
if (StringUtils.isEmpty(password)||!password.equals(enpassword)){
count++;
//半小时后失效
redisTemplate.opsForValue().set(checkPrefix+username,count,30,TimeUnit.MINUTES);
throw new GuliException("账号密码不正确");
}
}
校验前,会查询redis中是否存在该用户名的key存在。
checkPassword方法根据接口接收到的用户名和密码与数据库搜索到的进行比较,如果正确则返回登录成功。如果失败,则会根据用户名设置一个key存进redis中,赋值value为1,设定过期时间为30分钟。
如果该key存在,则让value+1,达到一定次数时,返回密码输错n次,请30分钟后尝试
其中的key值的命名以及错误的次数可以在配置文件中设置,然后此处引用。