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

【NFTurbo】基于Redisson滑动窗口实现验证码发送限流

【NFTurbo】基于Redisson滑动窗口实现验证码发送限流

  • 1. 场景
  • 2. 代码

1. 场景

服务在登录和注册的时候需要短信验证,为了防止被灰黑产抓包盗刷,需要限制次数,这里我们在前端做了按钮的置灰,但是后端接口还是要做防控的。

2. 代码

@GetMapping("/sendCaptcha")
public Result<Boolean> sendCaptcha(@IsMobile String telephone) {NoticeResponse noticeResponse = noticeFacadeService.generateAndSendSmsCaptcha(telephone);return Result.success(noticeResponse.getSuccess());
}
package cn.hollis.nft.turbo.notice.facade;import cn.hollis.nft.turbo.api.notice.response.NoticeResponse;
import cn.hollis.nft.turbo.api.notice.service.NoticeFacadeService;
import cn.hollis.nft.turbo.base.exception.SystemException;
import cn.hollis.nft.turbo.limiter.SlidingWindowRateLimiter;
import cn.hollis.nft.turbo.notice.domain.constant.NoticeState;
import cn.hollis.nft.turbo.notice.domain.entity.Notice;
import cn.hollis.nft.turbo.notice.domain.service.NoticeService;
import cn.hollis.nft.turbo.rpc.facade.Facade;
import cn.hollis.nft.turbo.sms.SmsService;
import cn.hollis.nft.turbo.sms.response.SmsSendResponse;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;import java.util.Date;
import java.util.concurrent.TimeUnit;import static cn.hollis.nft.turbo.api.notice.constant.NoticeConstant.CAPTCHA_KEY_PREFIX;
import static cn.hollis.nft.turbo.base.exception.BizErrorCode.SEND_NOTICE_DUPLICATED;/*** @author Hollis*/
@DubboService(version = "1.0.0")
public class NoticeFacadeServiceImpl implements NoticeFacadeService {@Autowiredprivate SlidingWindowRateLimiter slidingWindowRateLimiter;@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate NoticeService noticeService;@Autowiredprivate SmsService smsService;/*** 生成并发送短信验证码** @param telephone 接收验证码的手机号码* @return 验证码发送结果响应对象*/@Facade@Overridepublic NoticeResponse generateAndSendSmsCaptcha(String telephone) {// 使用滑动窗口限流器控制验证码发送频率,每个手机号60秒内只能发送1次Boolean access = slidingWindowRateLimiter.tryAcquire(telephone, 1, 60);if (!access) {throw new SystemException(SEND_NOTICE_DUPLICATED);}// 生成4位随机数字验证码String captcha = RandomUtil.randomNumbers(4);// 将验证码存储到Redis中,设置5分钟过期时间redisTemplate.opsForValue().set(CAPTCHA_KEY_PREFIX + telephone, captcha, 5, TimeUnit.MINUTES);Notice notice = noticeService.saveCaptcha(telephone, captcha);// 异步发送短信验证码Thread.ofVirtual().start(() -> {SmsSendResponse result = smsService.sendMsg(notice.getTargetAddress(), notice.getNoticeContent());if (result.getSuccess()) {notice.setState(NoticeState.SUCCESS);notice.setSendSuccessTime(new Date());noticeService.updateById(notice);} else {notice.setState(NoticeState.FAILED);notice.addExtendInfo("executeResult", JSON.toJSONString(result));noticeService.updateById(notice);}});return new NoticeResponse.Builder().setSuccess(true).build();}
}
package cn.hollis.nft.turbo.limiter;import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;/*** 滑动窗口限流服务** @author Hollis*/
public class SlidingWindowRateLimiter implements RateLimiter {private RedissonClient redissonClient;private static final String LIMIT_KEY_PREFIX = "nft:turbo:limit:";public SlidingWindowRateLimiter(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@Overridepublic Boolean tryAcquire(String key, int limit, int windowSize) {RRateLimiter rRateLimiter = redissonClient.getRateLimiter(LIMIT_KEY_PREFIX + key);if (!rRateLimiter.isExists()) {rRateLimiter.trySetRate(RateType.OVERALL, limit, windowSize, RateIntervalUnit.SECONDS);}return rRateLimiter.tryAcquire();}
}
http://www.dtcms.com/a/340833.html

相关文章:

  • 如何在高并发下,保证共享数据的一致性
  • RabbitMQ的架构设计是什么样的
  • Unity 之如何使用Pico4u锚点功能实现一个世界锁GameRoot
  • 第二十七天:游戏组队问题
  • 【GPT入门】第49课 LlamaFacotory 训练千问
  • Mac电脑 Pixelmator Pro 专业图像处理【媲美PS】
  • UE5 InVideo插件打包报错
  • Linux 下实现“连 root 都无法查看和删除”的加密文件夹(附一键挂载 + 自动超时退出)
  • 【P7071 [CSP-J2020] 优秀的拆分 - 洛谷 https://www.luogu.com.cn/problem/P7071】
  • 织梦素材站网站源码 资源付费下载交易平台源码
  • 棒子出品,无须破解!
  • PyTorch API 6
  • 深度学习实战116-基于Qwen大模型与层次化对齐评分模型(HASM)的中学数学主观题自动批改系统
  • 常见开源协议详解:哪些行为被允许?哪些被限制?
  • AV1视频编码器2024-2025技术进展与行业应用分析
  • 本地部署的终极多面手:Qwen2.5-Omni-3B,视频剪、音频混、图像生、文本写全搞定
  • 第四章:大模型(LLM)】07.Prompt工程-(5)self-consistency prompt
  • PyTorch 深度学习常用函数总结
  • 使用 SSH 方式克隆 GitHub 仓库没有权限解决办法
  • [递归回溯]679. 24 点游戏
  • LINUX 820 shell:shift,expect
  • 第5.8节:awk自增自减运算
  • linux的内核符号表
  • 服装外贸系统软件怎么用才高效防风险?
  • 曲面的交线的切向量计算及其在坐标平面投影的几何分析
  • 有向图(Directed Graph)和有向无环图(Directed Acyclic Graph,DAG)代码实践
  • 反向Shell(Reverse Shell)
  • Meta 再次重组人工智能部门
  • Visual Studio 2010 简体中文旗舰版 安装全过程详解(附安装包下载)
  • 常见的学术文献数据库