本文介绍了java开发中对于用户登录中,密码错误提示并限制登录做出分析和提供部分实现代码,通过Redis的StringRedisTemplate完成;
首先分为两部分,第一部分是一登录就进行的查询部分,通过之后进入的判断部分;
- 1.查询部分
- 首先在用户登录的时候传入用户名和密码,将自定义的缓存Key跟用户名组合去查询redis,判断是否存在;
- 然后如果有这个key说明用户已经输入错误过密码,那么再去查询加锁key跟用户名组合去查询redis,判断是否加锁key的存在,如果存在直接返回给前端用户已被锁定;
- 2.判断部分
- 首先查询数据库,判断账户名或密码是否错误,
如果是密码错误才进入下面的判断;- 查询redis是否存在缓存验证key,如果不存在就创建,值为1,如果已经存在就加1并更新redis的Key值,并提示用户输入错误了几次,返回给前端;
- 如果输入错误大于规定的次数就锁定账户,创建一个加锁key,设置失效时间为12小时,并返回前端超过限制,锁定12小时后重试;
- 如果在没有锁定前密码已经输入正确就删除缓存验证key,因为上面已经加了判断,所以无需管加锁key
//用户缓存验证key
public static final String LOGIN_USER_KEY= "dq.login.verify.%s";//用户加锁key
public static final String LOGIN_USER_LOCK_KEY= "dq.login.lock.%s";//用户冻结时间(分)
public static final int LOGIN_USER_LOCK_TIME= 10;//用户输入错误几次后提示用户
public static final int LOGIN_USER_LOCK_HINT_COUNT= 4;//用户输入错误几次后提示用户剩余次数
public static final int LOGIN_USER_LOCK_LIFE_COUNT= 1;//用户进入锁定的总次数
public static final int LOGIN_USER_LOCK_COUNT= 5;/*** 登录验证** 账户锁定判定:输入指定的次数后锁定账户,删除判定的key,启用锁key,设置过期时间,等锁key过期就可以重新登录* * @param username* 用户名* @param password* 密码* @return 结果*/
public Map login(String username, String password) {//登录时先判断redis是否有用户的keyString loginFailKey = String.format(LOGIN_USER_KEY, username);String loginValue = redisTemplate.opsForValue().get(loginFailKey);if(StrUtil.isNotEmpty(loginFailKey )){//用户加锁keyString loginLockKey = String.format(LOGIN_USER_LOCK_KEY, username);String lockValue = redisTemplate.opsForValue().get(loginLockKey);if(StrUtil.isNotEmpty(lockValue)){// 超过限制次数Long timeRest = redisTemplate.getExpire(loginLockKey, TimeUnit.MINUTES);throw new LoginFailLimitException("登录错误次数超过限制,请" + timeRest + "分钟后 再试");}}//xxx这里去写查询匹配账户名密码的代码
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx//如果密码错误
if (如果密码错误的判断条件) {//如果存在锁就提示if(StrUtil.isNotEmpty(loginValue)){int i = Integer.parseInt(loginValue);//给用户提示if(i==LOGIN_USER_LOCK_HINT_COUNT){redisTemplate.opsForValue().set(loginFailKey,i+1+"",12,TimeUnit.HOURS);throw new LoginFailLimitException("还剩"+LOGIN_USER_LOCK_LIFE_COUNT+"次机会,登录失败将锁定账户");//锁定账户,重置用户登录失败次数}else if(i==LOGIN_USER_LOCK_COUNT){redisTemplate.opsForValue().set(loginLockKey, DateUtil.date().toString(),LOGIN_USER_LOCK_TIME,TimeUnit.MINUTES);redisTemplate.delete(loginFailKey);throw new LoginFailLimitException("登录错误次数超过限制,请" + LOGIN_USER_LOCK_TIME + "分钟后再试");//登录失败次数加1} else {redisTemplate.opsForValue().set(loginFailKey,i+1+"",12,TimeUnit.HOURS);}}else {redisTemplate.opsForValue().set(loginFailKey,"1",12,TimeUnit.HOURS);}//如果登录成功,清空失败次数if(StrUtil.isNotEmpty(loginValue)){redisTemplate.delete(loginFailKey);}
}
下一篇:数字化工厂建设有别于传统业务模式