当前位置: 首页 > news >正文

登录失败次数限制

1. 概述

原始的UserService实现类只提供了基本的用户登录功能,没有对登录失败次数进行限制。攻击者可以通过暴力破解的方式不断尝试不同的密码组合来猜测用户密码,存在严重的安全风险。

通过增加用户登录失败次数限制功能,可以防止暴力破解攻击。通过在Redis中记录用户登录失败次数,当失败次数超过设定阈值时锁定账户一段时间,有效提高系统的安全性。

2. 实施方案

2.1 设计思路

通过在Redis中维护用户登录失败次数来实现登录失败次数限制功能:

  1. 用户每次登录失败时,增加该账户的失败计数
  2. 当失败次数超过设定阈值时,锁定账户一段时间
  3. 登录成功后清除失败计数

2.2 Redis存储设计

Key: login:failed:{account}
Value: 失败次数(整数)
Expire: - 未达到最大失败次数:1小时- 达到最大失败次数:锁定时间(默认30分钟)

2.3 配置项

在application-dev.yml中添加了新的配置项:

# 登录失败次数限制配置
login:max-failed-attempts: 5  # 最大失败次数lockout-duration: 1800  # 锁定时间(秒)

2.4 核心方法实现

2.4.1 isAccountLocked方法
/*** 检查账户是否被锁定* @param account 账户名,默认系统中的账户唯一* @return 是否被锁定*/
private boolean isAccountLocked(String account) {String key = LOGIN_FAILED_COUNT_PREFIX + account;Integer failedCount = loginFailedCountRedisUtil.get(key);return failedCount != null && failedCount >= maxFailedAttempts;
}
3.4.2 incrementFailedAttempts方法
/*** 增加登录失败计数* @param account 账户名*/
private void incrementFailedAttempts(String account) {String key = LOGIN_FAILED_COUNT_PREFIX + account;Integer currentCount = loginFailedCountRedisUtil.get(key);int newCount = (currentCount == null) ? 1 : currentCount + 1;// 如果达到最大失败次数,设置较长的过期时间if (newCount >= maxFailedAttempts) {loginFailedCountRedisUtil.set(key, newCount, (long) lockoutDuration);} else {// 否则设置较短的过期时间(1小时)loginFailedCountRedisUtil.set(key, newCount, 3600L);}
}
3.4.3 clearFailedAttempts方法
/*** 清除登录失败计数* @param account 账户名*/
private void clearFailedAttempts(String account) {String key = LOGIN_FAILED_COUNT_PREFIX + account;loginFailedCountRedisUtil.del(key);
}
3.4.4 修改login方法
@Override
public UserInfo login(LoginDTO loginDTO) {final String account = loginDTO.getAccount();final String password = loginDTO.getPassword();// 检查账户是否被锁定if (isAccountLocked(account)) {log.warn("账户已被锁定: {}", account);throw new GlobalException("账户已被锁定,请稍后再试");}// 根据account查询用户final List<User> list = this.list(Wrappers.<User>lambdaQuery().select(User::getId, User::getAvatar, User::getNickname, User::getPassword).eq(User::getAccount, account).ge(User::getStatus, UserStatus.ACTIVATED.getCode()));// 如果用户不存在或同账户的用户多于一条if (list == null || list.size() != 1) {log.error("账户有问题");// 增加登录失败计数incrementFailedAttempts(account);throw new GlobalException("账户有问题");}// 获取到查询到的用户final User user = list.get(0);// 密码不正确if (!BCrypt.checkpw(password, user.getPassword())) {log.error("密码错误");// 增加登录失败计数incrementFailedAttempts(account);throw new GlobalException("登录失败");}// 登录成功,清除失败计数clearFailedAttempts(account);// ... 其他登录逻辑
}

4. 使用示例

正确
错误
用户输入账户和密码
账户是否已锁定?
返回错误信息: 账户锁定
验证账户和密码
清除失败计数
正常登录
结束
记录失败次数到Redis
失败次数达到阈值?
锁定账户
返回错误信息: 账户锁定
结束
返回错误信息: 密码错误
结束

4.1 登录失败处理流程

  1. 用户输入错误的账户或密码
  2. 系统记录失败次数并存储到Redis
  3. 当失败次数达到阈值时,账户被锁定
  4. 锁定期间无法登录,返回错误信息
  5. 锁定时间过后自动解锁

4.2 登录成功处理流程

  1. 用户输入正确的账户和密码
  2. 系统验证通过
  3. 清除该账户的失败计数
  4. 正常登录流程

5. 优化效果

5.1 安全性提升

  • 有效防止暴力破解攻击
  • 限制恶意登录尝试次数
  • 提高系统整体安全性

5.2 资源保护

  • 减少无效登录请求对系统资源的消耗
  • 降低数据库查询压力
  • 提高系统稳定性

5.3 用户体验

  • 合理的失败次数限制不会影响正常用户
  • 明确的错误提示帮助用户理解锁定原因
  • 自动解锁机制避免长期锁定

6. 注意事项

  1. Redis性能: 失败次数存储在Redis中,需要注意Redis的性能和容量
  2. 配置调整: 根据实际业务需求调整最大失败次数和锁定时间
  3. 异常处理: 需要妥善处理Redis操作可能出现的异常
  4. 并发控制: 在高并发场景下需要注意Redis操作的并发控制
http://www.dtcms.com/a/573681.html

相关文章:

  • wordpress文章图片目录网站改版的seo注意事项
  • 【git】git clone含有lfs大文件时卡在resolving deltas(100%)的解决方案
  • 外贸和网站制作个人网站有什么内容
  • 开发一个完整的Electron应用程序
  • 从测试小白到高手:JUnit 5 核心注解 @BeforeEach 与 @AfterEach 的实战指南
  • App 怎么上架 iOS?从准备资料到开心上架(Appuploader)免 Mac 上传的完整实战流程指南
  • 智能安全管理 基于视觉分析的玩手机检测系统 手机行为AI模型训练 边缘计算手机行为监测设备
  • 做网站的必备软件php安防企业网站源码
  • 旅游自媒体网站怎么做c2c网站建设系统
  • Apache HTTP Server 2.4.65 详细安装教程(基于 CentOS 7)
  • 建行个人网站河池网站建设
  • 河北网站备案多久关于网站建设的请示范文
  • 坑#Spring#NullPointerException
  • 做视频网站用什么格式教育+wordpress模板下载
  • 排序算法
  • 网站排名推广安卓下载软件
  • Nginx 安全网关
  • 手机网站 像素旅游网站建设方案之目标
  • 2025年具身智能安全前沿:守护机器人时代的防失控策略
  • 中国机器人产业:迅猛崛起与未来征程
  • 购物消费打折
  • 深度解析Andrej Karpathy访谈:关于AI智能体、AGI、强化学习与大模型的十年远见
  • 网站403错误在线p图修改文字
  • 无锡住房建设网站社区网站建设方案书
  • 从零开始搭建 flask 博客实验(4)
  • 酒店预订数据分析及预测可视化
  • 直接IP做网站China wordpress
  • 大连建设网水电官网查询天津seo排名效果好
  • 对抗高级反爬:基于动态代理 IP 的浏览器指纹模拟与轮换策略
  • 真实场景:防止缓存穿透 —— 使用 Redisson 布隆过滤器