Java實現簡訊驗證碼--設定傳送間隔時間,以及有效時間(Java+Redis)
阿新 • • 發佈:2020-07-27
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