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