Java实现短信验证码--设置发送间隔时间,以及有效时间(Java+Redis)

Java 实现短信验证码 -- 设置发送间隔时间,以及有效时间(Java+Redis)

这篇文章,实现了 Java 发送手机短信验证码发送的间隔时间,以及手机验证码的有效时间和手机验证码格式的合法性验证,可以防止恶意刷接口

关于 Java 项目怎么连接 redis,请看这一篇文章 https://www.cnblogs.com/nanstar/p/13367747.html

代码部分

package com.zxjs.controller.app;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**

  • 发送短信验证码
    */
    @Api(value="发送短信验证码",description = "发送短信验证码,默认发送短信的间隔是一分钟",tags = {"发送短信验证码"})
    @RestController
    @RequestMapping("appISendSms")
    public class SendSMS {
    private final static Logger logger = LoggerFactory.getLogger(SendSMS.class);

    /**

    • 链接 redis 数据库,使用验证码的时候,只需要在其他的地方用 redis 查询这个手机号的验证码就可以了
      /
      static Jedis jedis = new Jedis("localhost");
      /
      *

    • 生成随机的六位验证码
      /
      static String sale = "";
      /
      *

    • @param args
      /
      public static void main(String[] args) throws InterruptedException{
      // 手机号测试部分
      sendSmsInfo("13683654784");
      }
      /
      *

    • 发送验证消息

    • 传入手机号,接收到的是用户的手机号码

    • @return
      */
      @ApiOperation(value="发送验证消息",notes = "发送验证消息,默认同一个手机号码发送短信间隔是一分钟, 加入手机号码格式验证,可使用时长是五分钟,可以有效防止恶意刷接口")
      @ApiImplicitParam(paramType = "query",name="phone",value = "0",required = true)
      @GetMapping("getReCode")
      @ResponseBody
      public static String sendSmsInfo(String phone){
      // 进入发送逻辑的时候生成随机验证码,六位数字
      sale = RandomStringUtils.randomNumeric(6);

      // 思路,每个手机号进来的时候,放到 redis 里面一个值,(手机号,验证码 + 开始时间)
      // 当这个用户再次来查询的时候,查看时间是否到达一分钟,到达的话可以发送验证码

      try {
      // 验证码有效时间,放到 redis 缓存里面(手机号,验证码 + 开始时间),根据开始时间来判断,达到了时间删掉缓存里面的手机号
      String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9])|(16[6]))\d{8}$";
      Pattern p = Pattern.compile(regex);
      Matcher m = p.matcher(phone);
      boolean isMatch = m.matches();
      if (! isMatch) {
      return "手机号码格式不正确, 请核对后重新输入!";
      } else {
      /检测 redis 是否开启,未开启的话,返回信息/
      if(jedis.ping() == "PONG"){
      return "Redis Is Not Run!";
      }
      // 当前时间秒数
      Long timemili = System.currentTimeMillis() / 1000;
      // System.out.println("当前的秒数" + timemili);
      // System.out.println(jedis.dbSize());
      // System.out.println(jedis.keys(""));
      /在这里写一个定时的 for 循环,用来取 redis 的手机号码信息,然后查询手机号码开始的时间,若是大于等于五分钟
      * 就给删除这个键值
      /

      // 创建多线程定时任务,延迟 1s 启动,每隔 1s 执行一次,是前一个任务开始时就开始计算时间间隔,但是会等上一个任务结束在开始下一个
      ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
      scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
      @Override
      public void run() {
      /执行程序的位置/
      // 首先取出所有的手机号 键信息,放到新的集合里
      Set setPhone = new HashSet();
      setPhone = jedis.keys("
      ");
      for (Object setInfo : setPhone) {
      // 判断这个键的值是不是超过五分钟,是的话就删除掉这个键
      System.out.println("计算结果"+ (System.currentTimeMillis() / 1000 - Long.parseLong(jedis.get(setInfo.toString()).substring(6))) );
      if(System.currentTimeMillis() / 1000 - Long.parseLong(jedis.get(setInfo.toString()).substring(6)) > 300){
      jedis.del(setInfo.toString());
      }
      // System.out.println(setInfo);
      }
      }
      }, 1, 2, TimeUnit.SECONDS);

       	<span class="hljs-comment">/**
       	 * 设置键值的时候先查询是否存在这个键值对,存在的话查看时长,不存在的话直接发送短信
       	 */</span>
       	<span class="hljs-type">boolean</span> <span class="hljs-variable">str</span> <span class="hljs-operator">=</span> jedis.exists(phone);
       	<span class="hljs-keyword">if</span> (! str) {
       		<span class="hljs-comment">//发送短息</span>
       		<span class="hljs-type">String</span> <span class="hljs-variable">recode</span> <span class="hljs-operator">=</span> SmsInfo(phone);
       		jedis.set(phone, (sale + timemili));
       		<span class="hljs-keyword">return</span> recode;
       	} <span class="hljs-keyword">else</span> {
       		<span class="hljs-type">String</span> <span class="hljs-variable">strT</span> <span class="hljs-operator">=</span> jedis.get(phone);
       		<span class="hljs-comment">//查看请求间隔,默认是一分钟,小于一分钟继续等待,超过一分钟发送短信</span>
       		<span class="hljs-keyword">if</span> (timemili - Long.parseLong(strT.substring(<span class="hljs-number">6</span>)) &lt; <span class="hljs-number">60</span>) {
      

// System.out.println("请一分钟后再次重试" + new Date());
return "请等待一分钟后再次重试!";
} else {
// 发送短息
String recode = SmsInfo(phone);
jedis.set(phone, (sale + timemili));
return recode;
}
}
}
}catch(Exception e){
logger.error(e.getMessage());
}
return "false";
}

<span class="hljs-comment">/**
 * 发送短息
 * <span class="hljs-doctag">@return</span>
 */</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title function_">SmsInfo</span><span class="hljs-params">(String phone)</span>{
    这里设置短信验证码的接口和账户密码部分(自己购买的接口在这里)
    <span class="hljs-type">String</span> <span class="hljs-variable">url</span> <span class="hljs-operator">=</span><span class="hljs-string">"http://www.ztsms.cn/sendNSms.do"</span>;
    <span class="hljs-type">String</span> <span class="hljs-variable">username</span> <span class="hljs-operator">=</span><span class="hljs-string">""</span>;<span class="hljs-comment">//内容</span>
    <span class="hljs-type">String</span> <span class="hljs-variable">password</span> <span class="hljs-operator">=</span><span class="hljs-string">""</span>;<span class="hljs-comment">//密码</span>
    <span class="hljs-type">String</span> <span class="hljs-variable">mobile</span> <span class="hljs-operator">=</span> phone;      <span class="hljs-comment">//号码</span>
    <span class="hljs-type">String</span> <span class="hljs-variable">content</span> <span class="hljs-operator">=</span><span class="hljs-string">"您本次操作的的验证码是:"</span>+sale+<span class="hljs-string">",验证码五分钟内有效,请不要把验证码发送给别人!"</span>;<span class="hljs-comment">//内容</span>
    <span class="hljs-type">String</span> <span class="hljs-variable">productid</span> <span class="hljs-operator">=</span><span class="hljs-string">""</span>; <span class="hljs-comment">//产品id</span>
    <span class="hljs-type">String</span> <span class="hljs-variable">xh</span> <span class="hljs-operator">=</span><span class="hljs-string">""</span>;<span class="hljs-comment">//设置为空</span>
    <span class="hljs-type">String</span> <span class="hljs-variable">tkey</span> <span class="hljs-operator">=</span> TimeUtil.getNowTime(<span class="hljs-string">"yyyyMMddHHmmss"</span>);
    <span class="hljs-keyword">try</span>{
        content= URLEncoder.encode(content,<span class="hljs-string">"utf-8"</span>);
    }<span class="hljs-keyword">catch</span> (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    String param=<span class="hljs-string">"gateway="</span>+url+<span class="hljs-string">"&amp;username="</span>+username+<span class="hljs-string">"&amp;password="</span>+ MD5Gen.getMD5(MD5Gen.getMD5(password)+tkey)+<span class="hljs-string">"&amp;tkey="</span>+tkey+<span class="hljs-string">"&amp;mobile="</span>+mobile+<span class="hljs-string">"&amp;content="</span>+content+<span class="hljs-string">"&amp;productid="</span>+productid+<span class="hljs-string">"&amp;xh"</span>+xh;

// String ret= HttpRequest.sendGet(url, param);//sendPost or sendGet 即 get 和 post 方式
System.out.println("ret:"+ret+param);
return sale;
}

}

用到的工具类的部分

phoneUtils https://files.cnblogs.com/files/nanstar/phoneUtils.zip