【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;
    }
相关推荐
乐悠小码几秒前
数据结构------队列(Java语言描述)
java·开发语言·数据结构·链表·队列
史努比.2 分钟前
Pod控制器
java·开发语言
2的n次方_5 分钟前
二维费用背包问题
java·算法·动态规划
皮皮林5515 分钟前
警惕!List.of() vs Arrays.asList():这些隐藏差异可能让你的代码崩溃!
java
莳光.6 分钟前
122、java的LambdaQueryWapper的条件拼接实现数据sql中and (column1 =1 or column1 is null)
java·mybatis
程序猿麦小七10 分钟前
基于springboot的景区网页设计与实现
java·spring boot·后端·旅游·景区
weisian15117 分钟前
认证鉴权框架SpringSecurity-2--重点组件和过滤器链篇
java·安全
蓝田~19 分钟前
SpringBoot-自定义注解,拦截器
java·spring boot·后端
明月清风徐徐19 分钟前
Scrapy爬取豆瓣电影Top250排行榜
python·selenium·scrapy
theLuckyLong20 分钟前
SpringBoot后端解决跨域问题
spring boot·后端·python