java + servlet+ jsp實現發送手機短信驗證碼
【1】選擇平台,完成認證。
短信登陸平台很多,自己可以看個人愛好選擇。
我們使用的API平台是:秒嘀雲: https://sms.miaodiyun.com/login.html
注冊該平台,完成認證就可以獲取到參數:ACCOUNT SID , AUTH TOKEN , API
【2】創建短信模板 (該模板必須創建,通過平台審核只會才可以使用,而且后續的參數 smsContent 要和模板中的一致 )
【3】發送短信接口
http://www.miaodiyun.com/doc/https_sms.html
編寫java手機短信發送代碼
【4】項目目錄結構 (idea 中創建的普通web工程)
【5】Config.java

1 public class Config { 2 /** 3 * url前半部分 4 */ 5 public static final String BASE_URL = " https://openapi.miaodiyun.com/distr*******dSMS"; 6 7 /** 8 * 開發者注冊后系統自動生成的賬號,可在官網登錄后查看 9 */ 10 public static final String ACCOUNT_SID = "fcf340ac***********915927"; 11 12 /** 13 * 開發者注冊后系統自動生成的TOKEN,可在官網登錄后查看 14 */ 15 public static final String AUTH_TOKEN = "648384a1***********2c33e4f"; 16 17 /** 18 * 響應數據類型, JSON或XML 19 */ 20 public static final String RESP_DATA_TYPE = "JSON"; 21 }
【6】http請求工具

1 package com.miaodi.comment; 2 3 4 5 import org.apache.commons.codec.digest.DigestUtils; 6 7 import java.io.BufferedReader; 8 import java.io.IOException; 9 import java.io.InputStreamReader; 10 import java.io.OutputStreamWriter; 11 import java.net.URL; 12 import java.net.URLConnection; 13 14 /** 15 * http請求工具 16 */ 17 public class HttpUtil { 18 /** 19 * 構造通用參數timestamp、sig和respDataType 20 * 21 * @return 22 */ 23 public static String createCommonParam(String sid,String token) { 24 // 時間戳 25 long timestamp = System.currentTimeMillis(); 26 // 簽名 27 String sig = DigestUtils.md5Hex(sid + token + timestamp); 28 return "×tamp=" + timestamp + "&sig=" + sig + "&respDataType=" + Config.RESP_DATA_TYPE; 29 } 30 31 /** 32 * post請求 33 * 34 * @param url 35 * 功能和操作 36 * @param body 37 * 要post的數據 38 * @return 39 * @throws IOException 40 */ 41 public static String post(String url, String body) { 42 System.out.println("body:" + System.lineSeparator() + body); 43 44 String result = ""; 45 try { 46 OutputStreamWriter out = null; 47 BufferedReader in = null; 48 URL realUrl = new URL(url); 49 URLConnection conn = realUrl.openConnection(); 50 51 // 設置連接參數 52 conn.setDoOutput(true); 53 conn.setDoInput(true); 54 conn.setConnectTimeout(5000); 55 conn.setReadTimeout(20000); 56 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 57 // 提交數據 58 out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); 59 out.write(body); 60 out.flush(); 61 62 // 讀取返回數據 63 in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); 64 String line = ""; 65 boolean firstLine = true; // 讀第一行不加換行符 66 while ((line = in.readLine()) != null) { 67 if (firstLine) { 68 firstLine = false; 69 } else { 70 result += System.lineSeparator(); 71 } 72 result += line; 73 } 74 75 } catch (Exception e) { 76 e.printStackTrace(); 77 } 78 return result; 79 } 80 81 /** 82 * 回調測試工具方法 83 * 84 * @param url 85 * @return 86 */ 87 public static String postHuiDiao(String url, String body) { 88 String result = ""; 89 try { 90 OutputStreamWriter out = null; 91 BufferedReader in = null; 92 URL realUrl = new URL(url); 93 URLConnection conn = realUrl.openConnection(); 94 95 // 設置連接參數 96 conn.setDoOutput(true); 97 conn.setDoInput(true); 98 conn.setConnectTimeout(5000); 99 conn.setReadTimeout(20000); 100 101 // 提交數據 102 out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); 103 out.write(body); 104 out.flush(); 105 106 // 讀取返回數據 107 in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); 108 String line = ""; 109 boolean firstLine = true; // 讀第一行不加換行符 110 while ((line = in.readLine()) != null) { 111 if (firstLine) { 112 firstLine = false; 113 } else { 114 result += System.lineSeparator(); 115 } 116 result += line; 117 } 118 } catch (Exception e) { 119 e.printStackTrace(); 120 } 121 return result; 122 } 123 }
【7】獲取驗證碼類

1 package com.miaodi.getcode; 2 3 import com.alibaba.fastjson.JSONObject; 4 import com.miaodi.comment.Config; 5 import com.miaodi.comment.HttpUtil; 6 7 import java.net.URLEncoder; 8 9 /** 10 * @author: 張瑛 11 * @date: 2019/7/5-12:22 12 */ 13 public class GetMessageCode { 14 15 private static String accountSid = Config.ACCOUNT_SID; 16 private static String rod=smsCode(); //生成一個隨機驗證碼 17 private static String smsContent = "【南京車紛享汽車服務有限公司】登錄驗證碼:"+rod +",如非本人操作,請忽略此短信"; 18 19 //創建驗證碼 20 public static String smsCode(){ 21 String random=(int)((Math.random()*9+1)*100000)+""; 22 return random; 23 } 24 25 //根據相應的手機號發送驗證碼 26 public static String getCode(String phone){ 27 String tmpSmsContent = null; 28 try{ 29 tmpSmsContent = URLEncoder.encode(smsContent, "UTF-8"); 30 }catch(Exception e){ 31 e.getMessage(); 32 } 33 34 String url = Config.BASE_URL; 35 String body = "accountSid=" + accountSid + "&to=" + phone + "&smsContent=" + tmpSmsContent 36 + HttpUtil.createCommonParam(Config.ACCOUNT_SID,Config.AUTH_TOKEN); 37 38 // 提交請求 39 String result = HttpUtil.post(url, body); 40 41 42 //字符串轉json對象 43 JSONObject jsonObject = JSONObject.parseObject(result); 44 String respCode = jsonObject.getString("respCode"); 45 46 System.out.println("驗證碼:"+rod); 47 System.out.println("結果碼:"+respCode); 48 49 //反饋-00000狀態碼標識請求成功, 50 String defaultRespCode="0000"; 51 if(defaultRespCode.equals(respCode)){ 52 return rod; 53 }else{ 54 return defaultRespCode; 55 } 56 } 57 58 }
【8】servlet類

1 package com.tencent.loginservlet; 2 3 import com.miaodi.getcode.GetMessageCode; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.annotation.WebServlet; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 import java.io.IOException; 11 12 /** 13 * @author: 張瑛 14 * @date: 2019/7/5-10:37 15 */ 16 @WebServlet(name = "LoginServlet",urlPatterns = "/sendSMS") 17 public class LoginServlet extends HttpServlet { 18 19 /** serialVersionUID*/ 20 private static final long serialVersionUID = 1L; 21 22 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 23 request.setCharacterEncoding("utf-8"); 24 String phone=request.getParameter("phone"); 25 //根據獲取到的手機號發送驗證碼 26 String code = GetMessageCode.getCode(phone); 27 System.out.println("返回code"+code); 28 response.getWriter().print(code); 29 30 } 31 32 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 33 this.doPost(request,response); 34 } 35 36 }
【9】login.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <% 3 String path = request.getContextPath(); 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 5 %> 6 <html> 7 <head> 8 <base href="<%=basePath%>"> 9 <title>測試短信登陸</title> 10 </head> 11 <meta http-equiv="pragma" content="no-cache"> 12 <meta http-equiv="cache-control" content="no-cache"> 13 <meta http-equiv="expires" content="0"> 14 15 <link rel="stylesheet" href="CSS/bootstrap/bootstrap.min.css" /> 16 <script type="text/javascript" src="js/jQuery/jquery-3.4.1.js"></script> 17 <style type="text/css"> 18 #login { 19 width: 450px; 20 height: 100px; 21 margin: 126px auto; 22 } 23 24 #btn { 25 margin-left: 100px; 26 margin-top: -25px; 27 width: 120px; 28 height: 25px; 29 font-size: 11px; 30 } 31 32 body { 33 background-color: #ecfcf9; 34 } 35 </style> 36 </head> 37 <script type="text/javascript"> 38 var InterValObj; //timer變量,控制時間 39 var count = 60; //間隔函數,1秒執行 40 var curCount;//當前剩余秒數 41 42 function sendMessage() { 43 curCount = count; 44 $("#btn").attr("disabled", "true"); 45 $("#btn").val(curCount + "秒后可重新發送"); 46 InterValObj = window.setInterval(SetRemainTime, 1000); //啟動計時器,1秒執行一次請求后台發送驗證碼 TODO 47 } 48 //timer處理函數 49 function SetRemainTime() { 50 if (curCount == 0) { 51 window.clearInterval(InterValObj);//停止計時器 52 $("#btn").removeAttr("disabled");//啟用按鈕 53 $("#btn").val("重新發送驗證碼"); 54 } else { 55 curCount--; 56 $("#btn").val(curCount + "秒后可重新發送"); 57 } 58 } 59 </script> 60 61 <body> 62 <div class="container"> 63 <div id="login"> 64 <fieldset> 65 <div id="legend" class=""> 66 <legend class="">用戶登錄</legend> 67 </div> 68 <form class="form-horizontal" role="form"> 69 70 <div class="form-group"> <label class="col-sm-2 control-label">手機號</label> 71 <div class="col-sm-5"> 72 <input type="text" class="form-control" id="phone" name="phone" placeholder="請輸入您的手機號" required> 73 </div> 74 </div> 75 76 <div class="form-group"> <label class="col-sm-2 control-label">驗證碼</label> 77 <div class="col-sm-3"> 78 <input type="code" class="form-control" id="code" name="code" placeholder="驗證碼" required> 79 <input class="btn btn-default" id="btn" name="btn" value="發送驗證碼" /> 80 </div> 81 </div> 82 83 <div class="form-group"> 84 <div class="col-sm-offset-2 col-sm-10"> 85 <button type="button" class="btn btn-success" id="lo">手機號登錄</button> 86 </div> 87 </div> 88 89 </form> 90 </fieldset> 91 </div> 92 </div> 93 </body> 94 95 <script type="text/javascript"> 96 var sms = ""; 97 $("#btn").click(function() { 98 var phone = $("#phone").val(); 99 if (phone != "") { 100 sendMessage(); 101 $.ajax({ 102 url : "sendSMS", //發送請求 103 type : "post", 104 data : { 105 "phone" : phone 106 }, 107 success : function(result) { 108 sms = result; 109 } 110 }); 111 } else { 112 alert("請輸入手機號"); 113 return false; 114 } 115 }); 116 $("#lo").click(function() { 117 var code = $("#code").val(); 118 if (code == "") { 119 alert("請輸入驗證碼"); 120 } else { 121 if (sms == code) { 122 window.location.href = "success.jsp"; 123 } else { 124 alert("驗證碼錯誤"); 125 } 126 ; 127 } 128 ; 129 }); 130 </script> 131 132 </html>
【10】備注:
lib是一些jar包,jar可以從秒嘀雲平台的demo中導入到自己的工程中,也可以自己從網上下載,主要用到的是commons-codec-1.9.jar 做加密用的,fastjson-1.2.49.jar 是作json轉化用的,其他的沒啥用。
頁面中引入的bootstrap 和jQuery 庫 自己可以從網上下載。succee.jsp 等可以自定義。
實在需要源碼的:發郵件到 1953211318@qq.com 看見了就回,看不見就算了。
附上效果鏈接:http://106.12.207.20/SendSMS2_war/login.jsp