注册短信验证码防刷设计方案

1.需求:一定时间内禁止重复发送短信
    两个时间要求
    60秒后才可以重新发送短信验证码
    发送的短信验证码10分钟内有效

2.方案

方式一:前端增加校验倒计时,不到60秒按钮不给点击
简单,不安全,存在绕过的情况
方式二:增加Redis存储,发送的时候设置下额外的key,并且60秒后过期
非原子操作,存在不一致性,增加的额外的key - value存储,浪费空间
/**
 * 前置:判断是否重复发送
 *
 * 1、存储验证码到缓存
 *
 * 2、发送短信验证码
 *
 * 后置:存储发送记录
 **/
方式三:基于原先的key拼装时间戳
好处:满足了当前节点内的原子性,也满足业务需求

3.上代码--使用方式三

  public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) {

        //拼接key
        String cacheKey = String.format(RedisKey.CHECK_CODE_KEY,sendCodeEnum.name(),to);
        //根据key,然后从redis中查找是否存在
        String cacheValue = redisTemplate.opsForValue().get(cacheKey);

        //如果不为空,再判断是否是60秒内重复发送 0122_232131321314132
        if(StringUtils.isNotBlank(cacheValue)){
            long ttl = Long.parseLong(cacheValue.split("_")[1]);
            //当前时间戳-验证码发送的时间戳,如果小于60秒,则不给重复发送
            long leftTime = CommonUtil.getCurrentTimestamp() - ttl;
            if( leftTime < (1000*60)){
                log.info("重复发送短信验证码,时间间隔:{}秒",leftTime);
                return JsonData.buildResult(BizCodeEnum.CODE_LIMITED);
            }
        }
        //key不存在redis中,则生成验证码,发送短信
        String code = CommonUtil.getRandomCode(6);
        //生成拼接好验证码
        String value = code+"_"+CommonUtil.getCurrentTimestamp();
        redisTemplate.opsForValue().set(cacheKey,value,CODE_EXPIRED,TimeUnit.MILLISECONDS);

        if(CheckUtil.isEmail(to)){
            //发送邮箱验证码  TODO

        }else if(CheckUtil.isPhone(to)){

            //发送手机验证码
            smsComponent.send(to,smsConfig.getTemplateId(),code);
        }
        return JsonData.buildSuccess();
    }

 redis的key value

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值