当前位置:网站首页>Redis - 利用lua脚本控制密码错误次数超限,锁定账号
Redis - 利用lua脚本控制密码错误次数超限,锁定账号
2022-08-10 22:30:00 【技术日志】
Lua脚本:是一种Redis脚本语言,功能和管道类似,客户端可以批量向服务端发送多条语句;不过Lua脚本发送的语句间具备原子性,而管道发送的语句间不具备原子性。
Lua脚本代码: 将代码存于resource --> loginFailLimit.lua文件中;
local key = KEYS[1]
local limit = tonumber(ARGV[1]) ----> 设置限制的次数
local limitTime = tonumber(ARGV[2]) ----> 设置限制的时间
local lockTime = tonumber(ARGV[3]) ----> 账号锁定时间
local current = tonumber(redis.call('get', key) or '0')
-- 每limitTime时间内错limit次, 则账号锁定lockTime时间;
if(current == 0) then
redis.call('incrBy', key,"1");
redis.call('expire', key, limitTime);
return 0;
elseif (current < limit) then
redis.call('incrBy', key,"1");
return 0;
elseif (current == limit) then
redis.call('incrBy', key, "1");
redis.call('expire', key, lockTime);
return 1;
else
return 1;
end;
配置DefautRedisScript:
@Bean
public DefaultRedisScript<Boolean> redisScript() {
DefaultRedisScript<Boolean> objectDefaultRedisScript = new DefaultRedisScript<>();
objectDefaultRedisScript.setResultType(Boolean.class);
objectDefaultRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("loginFailLimit.lua")));
return objectDefaultRedisScript;
}
创建常量类:
public class RedisConstant {
public final static String LIMIT = "5"; //失败n次后锁定:
public final static String LIMIT_TIME = "600"; //时间范围:单位/秒
public final static String LOCK_TIME = "600"; //账号锁定时间: 单位/秒
}
创建RedisUtil工具类:
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Autowired
private DefaultRedisScript redisScript;
/**
* 获取key锁定状态:
* @param key
* @return true-锁定; false-未锁定;
*/
public Boolean getLockState(String key) {
return (Boolean) redisTemplate.execute(redisScript,
Arrays.asList(key),
RedisConstant.LIMIT, RedisConstant.LIMIT_TIME, RedisConstant.LOCK_TIME);
}
/**
* 获取key剩余锁定时间:
* @param key
* @return
*/
public long getLockInvalidTime(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 获取key的值:
* @param key
* @return
*/
public String getValueByKey(String key) {
return redisTemplate.opsForValue().get(key);
}
}
测试:
@SpringBootTest
class RedisLuaApplicationTests {
@Autowired
private RedisUtil redisUtil;
final String LOGIN_KEY = "PASSWORD_ERROR_KEY_";
@Test
void contextLoads() {
//模拟密码错误:
if (true){
String key = LOGIN_KEY + "userId";
Boolean flag = redisUtil.getLockState(key);
if (flag){
long lockInvalidTime = redisUtil.getLockInvalidTime(key);
System.out.println("密码频繁错误,已被锁定!请"+lockInvalidTime+"秒后重新登陆或者联系系统管理员!");
return;
}
String value = redisUtil.getValueByKey(key);
int i = Integer.parseInt(RedisConstant.LIMIT) - Integer.parseInt(value);
System.out.println("密码错误,剩余"+i+"次机会");
return;
}
}
}
边栏推荐
猜你喜欢
Detailed installation steps and environment configuration of geemap
MySQL:MySQL的集群——主从复制的原理和配置
链表相加(二)
Glide监听Activity生命周期源码分析
CFdiv2-Beautiful Mirrors-(期望)
August 10, 2022: Building Web Applications for Beginners with ASP.NET Core -- Creating Web UIs with ASP.NET Core
QT笔记——QT工具uic,rcc,moc,qmake的使用和介绍
面试官: AMS在Android起到什么作用,简单的分析下Android的源码
【640. 求解方程】
谁是边缘计算服务的采购者?是这六个关键角色
随机推荐
RecyclerView上下滑动时,不调用onBindViewHolder 导致列表的item不刷新
ASCII、Unicode和UTF-8
今日睡眠质量记录75分
如何成为一名正义黑客?你应该学习什么?
gcc492 compile `.rodata‘ can not be used when making a PIE object; recompile with -fPIE
HanLP词性表
交换机和生成树知识点
JS use regular expressions in g model and non g difference
JS学习 2022080
威纶通触摸屏如何在报警的同时,显示出异常数据的当前值?
Nodes in the linked list are flipped in groups of k
阿里云新增三大高性能计算解决方案,助力生命科学行业快速发展
uni-app微信小程序——下拉多选框
【640. 求解方程】
MySQL:MySQL的集群——主从复制的原理和配置
高学历毕业生,该学单片机还是plc?
CIKM2022 | 基于双向Transformers对比学习的序列推荐
RK3399平台开发系列讲解(内核驱动外设篇)6.35、IAM20680陀螺仪介绍
实例054:位取反、位移动
基于交流潮流的电力系统多元件N-k故障模型研究(Matlab代码实现)【电力系统故障】