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);
/**
* 設置鍵值的時候先查詢是否存在這個鍵值對,存在的話查看時長,不存在的話直接發送短信
*/
boolean str = jedis.exists(phone);
if (! str) {
//發送短息
String recode = SmsInfo(phone);
jedis.set(phone, (sale + timemili));
return recode;
} else {
String strT = jedis.get(phone);
//查看請求間隔,默認是一分鍾,小於一分鍾繼續等待,超過一分鍾發送短信
if (timemili - Long.parseLong(strT.substring(6)) < 60) {
// 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";
}
/**
* 發送短息
* @return
*/
public static String SmsInfo(String phone){
這里設置短信驗證碼的接口和賬戶密碼部分(自己購買的接口在這里)
String url ="http://www.ztsms.cn/sendNSms.do";
String username ="";//內容
String password ="";//密碼
String mobile = phone; //號碼
String content ="您本次操作的的驗證碼是:"+sale+",驗證碼五分鍾內有效,請不要把驗證碼發送給別人!";//內容
String productid =""; //產品id
String xh ="";//設置為空
String tkey = TimeUtil.getNowTime("yyyyMMddHHmmss");
try{
content= URLEncoder.encode(content,"utf-8");
}catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String param="gateway="+url+"&username="+username+"&password="+ MD5Gen.getMD5(MD5Gen.getMD5(password)+tkey)+"&tkey="+tkey+"&mobile="+mobile+"&content="+content+"&productid="+productid+"&xh"+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