美文网首页
短信验证码防刷

短信验证码防刷

作者: 前进的码农 | 来源:发表于2022-05-29 19:59 被阅读0次

    常规手段

    • 前端加一分钟倒计时(光加这个解决不了问题,可以抓包直接绕过去)
    • 校验码(人机互动)
    • 后端加时间,一分钟内准重新发送
    • 后端加10分钟内验证码过期
    • 一个手机一天内限制发送次数(这个一般短信云厂商会提供)

    实现流程图

    未命名文件 (1).png

    代码实现

    核心 pom介绍

    图形验证码

            <!--图形验证码 -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>kaptcha-spring-boot-starter</artifactId>
                <version>1.1.0</version>
            </dependency>
    

    存储使用的是redis

           <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>io.lettuce</groupId>
                        <artifactId>lettuce-core</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--客户端使用 jedis-->
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
            </dependency>
    

    实现代码

    图形验证码

    @GetMapping("kaptcha")
        public void kaptcha(HttpServletRequest request, HttpServletResponse response){
            String captchaText = captchaProducer.createText();
            log.info("验证码内容:{}",captchaText);
            //存储redis,配置过期时间,3分钟图形验证码过期
            redisTemplate.opsForValue().set(getCaptchaKey(request),captchaText,60*1000*3, TimeUnit.MILLISECONDS);
    
            BufferedImage bufferedImage = captchaProducer.createImage(captchaText);
    
            try (ServletOutputStream outputStream = response.getOutputStream()){
    
                ImageIO.write(bufferedImage,"jpg",outputStream);
                outputStream.flush();
    
            } catch (IOException e) {
                log.error("获取流出错:{}",e.getMessage());
            }
            return;
        }
     /**
         * 根据浏览器明细获取key
         *
         * @param request
         * @return
         */
        private String getCaptchaKey(HttpServletRequest request) {
            String ip = CommonUtil.getIpAddress(request);
            String userAgent = request.getHeader("User-Agent");
            String key = "sms-service:captcha:" + CommonUtil.MD5(ip + userAgent);
            log.info("图形验证码key:{}", key);
            return key;
        }
    

    短信部分核心代码

      @PostMapping("send_code")
      public R send(HttpServletRequest request, @RequestBody SmsReq smsReq){
          String key = getCaptchaKey(request);
          String cacheCacha = redisTemplate.opsForValue().get(key);
    
          if (!StringUtils.isEmpty(cacheCacha)&&cacheCacha.equalsIgnoreCase(smsReq.getCatcha())){
              redisTemplate.delete(key);
              return sendService.send(smsReq.getTel());
          }else{
              return R.error(-1,"图形验证码错误");
          }
    
      }
    @Override
      public R send(String to) {
          String cacheKey =String.format(Constant.SMS_LOGIN_KEY,to);
          String cacheCode = redisTemplate.opsForValue().get(cacheKey);
          if (cacheCode!=null&&!StringUtils.isNotBlank(cacheCode)){
              String ttl =  cacheCode.split("_")[1];
              Long time = System.currentTimeMillis()-Long.parseLong(ttl);
              if (time>60*1000){
                  return R.error(2,"请稍后再发");
              }
          }
          //这里默认验证码为6666
          String code = "6666";
          String codeValue = code+"_"+System.currentTimeMillis();
          //模拟发送短信
          smsComponent.send(to,code);
          //验证码有效期10分钟有效
          redisTemplate.opsForValue().set(cacheKey,codeValue,10*60*1000, TimeUnit.MILLISECONDS);
          return R.success("");
      }
    

    全部代码地址

    https://gitee.com/ethanlab/simple/tree/master/simple-sms

    相关文章

      网友评论

          本文标题:短信验证码防刷

          本文链接:https://www.haomeiwen.com/subject/itmaoltx.html