# 登录重试次数限制

  用户登录提供的信息错误,比如密码错误,不断进行尝试,会带来安全隐患。 如果不对登录接口进行限制,则可能会造成暴力破解的情况发生。除了对登录接口进行限流之外,还可以通过限制重试次数来提高安全性。

  Heimdall 框架提供了一个通用的基于缓存的重试限制策略。基本原理就是:当用户开始登录验证,对提交次数进行缓存记录,并设置缓存过期时间(超限后锁定期),每次提交出现错误就递增,当达到允许的出错上限后,拒绝登录。当缓存中的数据到期被清理后,恢复可登录状态,允许登录。

要使用此功能,需要首先进行注册,如下所示:

    /**
     * 登录重试次数限制
     *
     * @return the login password retry limit
     */
    @Bean
    public LoginPasswordRetryLimit loginPasswordRetryLimit() {
    	//Caffeine 缓存
        final CaffeineLoginPasswordRetryLimitImpl loginPasswordRetryLimit = new CaffeineLoginPasswordRetryLimitImpl();
        //Redis 缓存
       // final RedisLoginPasswordRetryLimitImpl loginPasswordRetryLimit   = new RedisLoginPasswordRetryLimitImpl(stringRedisTemplate);
        //允许尝试多少次?
        loginPasswordRetryLimit.setAttemptLimit(5);
        //超限了,锁定多少秒?
        loginPasswordRetryLimit.setLockedDuration(60);
        return loginPasswordRetryLimit;
    }

以登录为例:

public Serializable login(SysUserVO user) {
		//.........
        //如果密码错误,就认为用户在不断重试中,开始限次
        if (!passwordEncoder.matches(user.getPassword(), sysUserEntityByUsername.getPassword())) {
            //错误尝试次数限定:密码不对,记录一次,用 username 当做唯一缓存 key
            retryLimit.increase(sysUserEntityByUsername.getUsername());
            final int leftCount = retryLimit.leftCount(sysUserEntityByUsername.getUsername());
            if (leftCount == 0) {
                throw new HeimdallException("用户名密码错误,你已经剩下最后一次机会了,千万输入正确啊....");
            }
            throw new HeimdallException("用户名密码错误");
        }
        //......
		//构造 userdetails
        AppUserDetails userDetails = new AppUserDetails(userDTO);
        //执行登录
        final SimpleSession session = authenticationManager.login(userDetails);
        //认证通过后,把密码重试缓存清理掉
        retryLimit.remove(sysUserEntityByUsername.getUsername());
        //把 SessionId 返回
        return session.getId();
    }

上次更新:: 1/25/2021, 4:26:40 PM