使用Redis与lua脚本实现限制ip多次输入错误密码
AI 概述
使用 Redis 与 lua 脚本实现限制 ip 多次输入错误密码
不能锁 username,因为如果有人恶意保留破解密码的话。会导致用户本人无法登录。 这里我采用 以 ip 的方式进行锁定。利用 redis 设置 key:ip。value:当前 ip 尝试登录的次数
实现逻辑
逻辑简单,假设限制错误次数为 5
用户登录时。判断 key 是否存在。
如果 key...

使用 Redis 与 lua 脚本实现限制 ip 多次输入错误密码
不能锁 username,因为如果有人恶意保留破解密码的话。会导致用户本人无法登录。 这里我采用 以 ip 的方式进行锁定。利用 redis 设置 key:ip。value:当前 ip 尝试登录的次数
实现逻辑
逻辑简单,假设限制错误次数为 5
- 用户登录时。判断 key 是否存在。
- 如果 key 不存在,说明第一次登录。判断密码是否正确,==如果正确==什么都不干直接返回。==如果不正确==,设置 key 为 ip,value 为 1,并设置过期时间,返回错误信息。
- 如果存在 key,说明之前尝试登录过。判断 value 是否大于阈值,如果大于阈值刷新过期 并返回错误。如果小于阈值,==还要判断密码是否正确==。如果密码正确,删除 key 并返回正确信息。如果密码不正确,将 key 的 value 值+1 并重置过期时间,返回密码错误的信息。
以上主要注意两点 一点是有 key 的情况下密码正确需要删除 key。 二是有 key 的情况下,密码错误或者尝试次数大于阈值再次尝试登录,需要刷新过期时间。
使用 lua 脚本主要保证了对上述逻辑的原子性,因为涉及获取 key 的值并判断,然后将 key 的值+1 或 删除 key。
实现代码
Service 类加载时,加载 lua 脚本:
private static final DefaultRedisScript<Long> CHECK_LOGIN_SCRIPT;
// 类加载时 加载 lua 脚本
static {
CHECK_LOGIN_SCRIPT = new DefaultRedisScript<>();
CHECK_LOGIN_SCRIPT.setLocation(new ClassPathResource("checkLogin.lua"));
CHECK_LOGIN_SCRIPT.setResultType(Long.class);
}
具体校验方法,主要逻辑调用了 lua 脚本:
private void checkLoginInfo(UserLoginContext userLoginContext) {
String username = userLoginContext.getUsername();
String password = userLoginContext.getPassword();
//根据用户名查实体 从数据库
RPanUser entity = getRPanUserByUsername(username);
if (Objects.isNull(entity)){
throw new RPanBusinessException("用户名不存在");
}
String salt = entity.getSalt(); //获取盐值
String encPassword = PasswordUtil.encryptPassword(salt, password) ; //将前端传 的密码加密
String dbPassword = entity.getPassword(); //获取数据库的密码
// encPassword 表示前端传过来的 加密后的密码
// dbPassword 表示数据库中的 加密后的密码
// TODO 调用 lua 脚本判断 登录失败 登录成功 及锁定 ip
List<String> keys = new ArrayList<>();
String ipAddress = HttpLogEntityBuilder.getIpAddress(userLoginContext.getRequest()); //获取请求 ip
// key 设置为 ip+username,进行锁定
keys.add(UserConstants.CHECK_LOGIN_PREFIX + ipAddress + "_" + username);
// 执行 lua 脚本
Long result = (Long)redisTemplate.execute(CHECK_LOGIN_SCRIPT, keys, encPassword, dbPassword, UserConstants.CHECK_LOGIN_THRESHOLD, UserConstants.CHECK_LOGIN_EXPIRE);
if (result == 0){
throw new RPanBusinessException("用户名或密码不正确");
}
if (result == -1){
throw new RPanBusinessException("输入密码错误达到"+UserConstants.CHECK_LOGIN_THRESHOLD+"次,请 1 分钟后尝试");
}
// if (!Objects.equals(encPassword, dbPassword)) {
// throw new RPanBusinessException("密码信息不正确");
// }
//填入实体信息
userLoginContext.setEntity(entity);
}
lua 脚本,放在 resources 目录下:
-- 判断用户登录的 lua 脚本
local key1 = KEYS[1]
local password1 = ARGV[1]
local password2 = ARGV[2]
-- 阈值
local threshold = ARGV[3]
-- 过期时间
local expiretime = ARGV[4]
-- 判断 key 是否存在
local value = redis.call('get', key1)
-- 有 key
if value then
if(value >= threshold) then
redis.call('expire', key1, expiretime) -- 刷新过期时间
return -1 -- 输入密码错误达到 threshold 次,请 1 分钟后尝试
end
if(password1 == password2) then -- 校验正确,删除 key 并返回 1 表示通过
redis.call('del', key1)
return 1
else
redis.call('INCR', key1) -- key 的值+1
redis.call('expire', key1, expiretime) -- 刷新过期时间
return 0 -- 用户名或密码不正确
end
end
-- 没有 key
if(password1 == password2) then
return 1
else
redis.call('setex', key1, expiretime, 1) -- setex key [过期时间] 1
return 0 -- 用户名或密码不正确
end
以上就是关于使用 Redis 与 lua 脚本实现限制 ip 多次输入错误密码的全部内容,更多请关注码云笔记其它相关文章!
以上关于使用Redis与lua脚本实现限制ip多次输入错误密码的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 使用Redis与lua脚本实现限制ip多次输入错误密码
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 使用Redis与lua脚本实现限制ip多次输入错误密码

微信
支付宝