【java登录锁定功能】redis实现登录失败锁定账号

登录失败(账号密码<5次时不提示),>=5次时,锁定时间5min,最高密码错误次数为10,第十次密码输入错误后,提醒,"账号已停用,请联系管理员开通",次日0时,重新计算错误次数

代码实现

java 复制代码
    public static String LOGIN_FAIL_LOCK = "login:error:count:";
    public static String LOGIN_FAIL_COUNT = "lock";

    @GetMapping("login")
    public void login(String userName, String password) {
        RedisUtil redisUtil = new RedisUtil();
        TyqUser tyqUser = this.selectUserFromMysql(userName);
        // 判断当前账号是否被锁定
        String errorMessage = this.judgeLock(userName);
        if (StrUtil.isNotEmpty(errorMessage)) {
            throw new BizException(errorMessage);
        }
        String loginFailLockKey = LOGIN_FAIL_LOCK + userName;
        String loginFailCountKey = LOGIN_FAIL_COUNT + userName;
        String msg = null;
        if (!tyqUser.getPassword().equals(userName)) {
            // 密码错误,进行封禁账号
            msg = loginFailLockJudge(loginFailLockKey, loginFailCountKey, tyqUser.getId());
        } else {
            // 登录成功,清空对应的 锁定次数
            redisUtil.delete(loginFailCountKey);
            redisUtil.delete(loginFailLockKey);
        }
    }



    // 模拟从数据库查询user
    public TyqUser selectUserFromMysql(String userName){
        return new TyqUser();
    }

    // 判断当前账号是否可以进行登录
    public String judgeLock(String userName) {
        RedisUtil redisUtil = new RedisUtil();
        BizResponse<Object> bizResponse = null;
        if (StrUtil.isEmpty(userName)) {
            return null;
        }
        Map<String, Object> param = new HashMap<>();
        TyqUser user = this.selectUserFromMysql(userName);
        // 查询 user 的状态,是否停用,禁用
        if ("停用".equals(user.getStatus())) {
            return "账号已停用";
        }
        // 判断账号是否锁定,锁定就进行提示
        String msg = null;
        String loginFailLockKey = LOGIN_FAIL_LOCK + userName;
        String loginFailCountKey = LOGIN_FAIL_COUNT + userName;
        if (redisUtil.getObject(loginFailCountKey) != null) {
            String loginFailCountValue = String.valueOf(redisUtil.getObject(loginFailCountKey));
            if (Integer.parseInt(loginFailCountValue) > 4) {
                if (redisUtil.getObject(loginFailLockKey) != null) {
                    Long ttlForLoginFailLock = redisUtil.ttl(loginFailLockKey);
                    if (ttlForLoginFailLock > 0) {
                        String minuteLeft = TimeUtil.getMinuteStringFromSeconds(ttlForLoginFailLock);
                        msg = "输入错误次数过多, 请" + minuteLeft + "后再试";
                        return msg;
                    }
                }
            }
        }
        return msg;
    }

    public int updateStatus(String id, String status) {
        return 1;
    }
    // 登录失败次数校验
    public String loginFailLockJudge(String loginFailLockKey, String loginFailCountKey, String id) {
        RedisUtil redisUtil = new RedisUtil();
        // 当前时间到次日零点的剩余时间
        Long remainToZero = ChronoUnit.SECONDS.between(LocalDateTime.now(), LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0));
        // key
        String loginFailCountValue = redisUtil.get(loginFailCountKey);
        String msg = null;
        Long maxTtl = 5 * 60L;
        if (StrUtil.isNotEmpty(loginFailCountValue)) {
            Integer loginFailCount = Integer.parseInt(loginFailCountValue);
            loginFailCount ++;
            // 前5次登录失败,提示错误信息
            if (loginFailCount < 5) {
                redisUtil.setObjectAndExpireSeconds(loginFailLockKey, loginFailCount, remainToZero);
                redisUtil.setObjectAndExpireSeconds(loginFailCountKey, loginFailCount, remainToZero);
                msg = "密码错误,请再次输入";
                return msg;
            }
            if (loginFailCount < 10) {
                Long ttl = maxTtl;
                if(ttl > remainToZero) {
                    ttl = remainToZero;
                }
                redisUtil.setObjectAndExpireSeconds(loginFailLockKey, loginFailCount, ttl);
                redisUtil.setObjectAndExpireSeconds(loginFailCountKey, loginFailCount, ttl);
                String minuteLeft = TimeUtil.getMinuteStringFromSeconds(ttl);
                msg = "密码错误次数频繁,请" + minuteLeft + "后再试";
            } else {
                // 修改mysql中的账号状态
                this.updateStatus(id, "停用");
                msg = "账号已停用";
            }
        } else {
            // 第一次登录失败
            redisUtil.setObjectAndExpireSeconds(loginFailLockKey, "1", remainToZero);
            redisUtil.setObjectAndExpireSeconds(loginFailCountKey, "1", remainToZero);
            msg = "密码错误,请再次输入";
        }
        return msg;
    }
相关推荐
大泽泽的小可爱3 分钟前
ros中地面站和无人机跨平台数据传递,使用 UDP 进行跨平台传输(python代码)
python·udp·无人机
曹朋羽4 分钟前
java中的集合之List
java·开发语言·list
不会敲代码阿19 分钟前
mysql 日志恢复
java·数据库·mysql
LQS202020 分钟前
基于Python实现一个庆祝中秋节的小程序
开发语言·python·小程序
夜半罟霖21 分钟前
算法手撕面经系列(1)--手撕多头注意力机制
python·深度学习·算法
重生成为码农‍26 分钟前
Java高级Day40-QQ项目全代码
java·开发语言·算法
IT学长编程31 分钟前
计算机毕业设计 毕业季一站式旅游服务定制平台的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·毕业论文·计算机毕业设计选题·旅游服务定制平台·计算机毕业设计开题报告
2401_8543910833 分钟前
旅游网站开发:SpringBoot框架实战
spring boot·后端·旅游
一瓢一瓢的饮 alanchan34 分钟前
【运维监控】influxdb 2.0+grafana 监控java 虚拟机以及方法耗时情况(完整版)
java·grafana·jvm监控·influxdb 2.0·java 监控·java 方法耗时
fish_study_csdn41 分钟前
使用Django 搭建自动化平台
python·django·自动化