当前位置:网站首页>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;
}
}
}
边栏推荐
- STL-deque
- “数据引擎”开启前装规模量产新赛道,「智协慧同」崭露头角
- 亲测有效|处理风控数据特征缺失的一种方法
- 阿里云张新涛:支持沉浸式体验应用快速落地,阿里云云XR平台发布
- 华为HCIE云计算之Fusion Access桌面云
- 带着昇腾去旅行:一日看尽金陵城里的AI胜景
- 分享一个后台管理系统可拖拽式组件的设计思路
- Nodes in the linked list are flipped in groups of k
- 阿里云架构师金云龙:基于云XR平台的视觉计算应用部署
- What would happen if disconnecting during the process of TCP connection?
猜你喜欢
68:第六章:开发文章服务:1:内容梳理;article表介绍;创建【article】文章服务;
边缘与云计算:哪种解决方案更适合您的连接设备?
RK3399 platform development series explanation (kernel-driven peripherals) 6.35, IAM20680 gyroscope introduction
Qualcomm Platform Development Series Explanation (Application) Introduction to QCMAP Application Framework
ThreadLocal comprehensive analysis (1)
12 Recurrent Neural Network RNN2 of Deep Learning
VLAN huawei 三种模式
测试4年感觉和1、2年时没什么不同?这和应届生有什么区别?
爬虫request.get()出现错误
MySQL学习笔记(2)——简单操作
随机推荐
STL-deque
68: Chapter 6: Develop article services: 1: Content sorting; article table introduction; creating [article] article services;
BM7 list entry in central
leetcode:357. 统计各位数字都不同的数字个数
《DevOps围炉夜话》- Pilot - CNCF开源DevOps项目DevStream简介 - feat. PMC成员胡涛
过滤器
12 Recurrent Neural Network RNN2 of Deep Learning
虚拟地址空间
【640. Solving Equations】
STL-stack
BM7 链表中环的入口结点
H3C S5130 IRF做堆叠
pytorch tear CNN
合并k个已排序的链表
实例054:位取反、位移动
瑞幸咖啡第二季营收33亿:门店达7195家 更换CFO
RK3399 platform development series explanation (kernel-driven peripherals) 6.35, IAM20680 gyroscope introduction
uni-app微信小程序——下拉多选框
罗克韦尔AB PLC RSLogix5000中计数器指令使用方法介绍
Why general company will say "go back messages such as" after the end of the interview, rather than just tell the interviewer the result?