视频直播app源码,利用缓存实现连续登录失败后的时间等待

实现步骤:

1、用户在视频直播app源码中发起登录请求

2、后台验证是否失败次数过多,账户没有锁定的话就进入下面的步骤;否则直接返回

3、验证用户的账号 + 密码

3.1 验证成功:删除缓存
3.2 验证失败:统计最近10分钟时间窗口内的失败次数,如果达到5次则设置锁定缓存,返回

图解实现步骤:

在这里插入图片描述
代码实现细节:

登录失败计数器的key设计为:一串字符串 + 用户名(假设具有唯一性)+ 登录失败的时间

锁定登录操作的key设计为:一串字符串 + 用户名(假设具有唯一性)

private static final String FAIL_COUNT_REDIS_KEY = "login_fail_count";

private static final String LOCK_REDIS_KEY = "login_lock";

private static final String SEPARATOR = ":";

 

用户登录服务:

@Override
public String login(String username, String password) {
    // 验证用户是否被登录锁定
    boolean lock = isForbidden(username);
    if (lock) {
        return "Login authentication failed too many times. Please try again after " + unLockTime(username) + " minutes.";
    }
    // 验证用户名 + 密码
    boolean isLogin = userRepository.checkUsernameAndPassword(username, password);
    if (!isLogin) {
        // 登录失败
        setFailCounter(username);
        return "login fail";
    }
    // 登录成功 移除失败计数器
    deleteFilCounter(username);
    return "login success";
}

 

登陆失败的话,就给登录失败次数加一:

@Override
public void setFailCounter(String username) {
    // 获取当前时间
    Calendar cal = Calendar.getInstance();
    String minute = fastDateFormat.format(cal);

    // 登录失败次数 + 1
    String key = String.join(SEPARATOR, FAIL_COUNT_REDIS_KEY, username, minute);
    Integer count = redisTemplate.opsForValue().get(key);
    redisTemplate.opsForValue().increment(key, 1); // 如果key不存在的话就会以增量形式存储进来

    if (count == null) {
        redisTemplate.expire(key, 10, TimeUnit.MINUTES);
    } 

    // 如果失败次数大于5次,锁定账户
    List<String> windowsKeys = new ArrayList<>();
    for (int i = 0; i < 10; i ++) {
        windowsKeys.add(String.join(SEPARATOR, FAIL_COUNT_REDIS_KEY, username, fastDateFormat.format(cal)));
        cal.add(Calendar.MINUTE, -1);
    }
    List<Integer> countList = redisTemplate.opsForValue().multiGet(windowsKeys);

    assert countList != null;

    int total = 0;
    for (Integer c : countList) {
        total += c;
    }
    if (total >= maxFailTimes) {
        forbidden(username);
    }
}

 

如果登录成功,则删除失败次数计数器:

@Override
public void deleteFilCounter(String username) {
    Calendar cal = Calendar.getInstance();
    List<String> windowKeys = new ArrayList<>();
    for (int i = 0; i < 10; i ++) {
        windowKeys.add(String.join(SEPARATOR, FAIL_COUNT_REDIS_KEY, username, fastDateFormat.format(cal)));
        cal.add(Calendar.MINUTE, -1);
    }
    redisTemplate.delete(windowKeys);
}

 

失败次数超过5次则禁止登录,只需要设置一个缓存即可:

@Override
public void forbidden(String username) {
    String key = String.join(SEPARATOR, FAIL_COUNT_REDIS_KEY, username);
    redisTemplate.opsForValue().set(key, 1, 30, TimeUnit.MINUTES);
}

 

判断是否被禁止登录,只需要判断是否有上面方法设置的key即可:

@Override
public boolean isForbidden(String username) {
    try{
        return Boolean.TRUE.equals(redisTemplate.hasKey(String.join(SEPARATOR, FAIL_COUNT_REDIS_KEY, username)));
    }catch (Exception e){
        e.printStackTrace();
    }
    return false;
}

 

如果想要获取到用户具体需要几分钟才能解锁(用于提示信息),只需要查询缓存的过期时间:

private Long unLockTime(String username){
    String key = String.join(SEPARATOR, LOCK_REDIS_KEY, username);
    Long expireTime = redisTemplate.opsForValue().getOperations().getExpire(key, TimeUnit.MINUTES);
    if (expireTime == null){
        throw new RuntimeException("there is no unlock time");
    }
    return expireTime;
}

 

以上就是视频直播app源码,利用缓存实现连续登录失败后的

 

posted @ 2024-01-20 14:10  云豹科技-苏凌霄  阅读(7)  评论(0编辑  收藏  举报