02-手机短信验证码

基于阿里云的手机短信验证码

在这里插入图片描述

阿里云的短信平台:http://www.aliyun.com
搜索短信服务,进入短信服务控制台,设置AccessKey+签名+短信模板
SDK及DEMO下载:https://help.aliyun.com/document_detail/55359.html

注意事项:阿里云短信服务,1条验证码 0.045元,需要有余额才能发送!

1. 环境依赖

  • bootstrap 框架依赖导入
  • bootstrapValidator 校验依赖导入
  • jQuery 函数库导入
  • aliyun sdk jar 包依赖导入
  • gson jar 包依赖导入

环境依赖

2. 页面表单 html

register.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>阿里云短信验证码测试</title>
<link href="${pageContext.request.contextPath}/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/bootstrapValidator/css/bootstrapValidator.min.css" rel="stylesheet">
<script src="${pageContext.request.contextPath}/js/jquery-3.5.1.min.js"></script>
<script src="${pageContext.request.contextPath}/bootstrap/js/bootstrap.min.js"></script>
<script src="${pageContext.request.contextPath}/bootstrapValidator/js/bootstrapValidator.min.js"></script>

<script src="${pageContext.request.contextPath}/js/smsAndValidator.js"></script>
</head>
<body>

<form id="myForm" action="${pageContext.request.contextPath}/user">
<input type="hidden" name="methodName" value="regist"/>
<div class="user-form-item form-group">
手机:<input name="user_tel" class="user-input" type="text" placeholder="手机号" id="user_tel">
</div>
<div class="user-form-item form-group">
密码:<input name="user_password" class="user-input" type="password" placeholder="密码">
</div>
<div class="user-form-item form-group">
验证码:<input name="qrCode" class="user-input user-input-adjust" type="text" placeholder="短信验证码">
<button type="button" class="qrcode" onclick="sendSMS()">发送验证码</button>
</div>
<div class="user-form-item">
<label>
<input class="user-check" type="checkbox" checked="false" value="yes">
<span class="cos_span">
注册即表示同意<a class="keyword-blue-pale">《xx网用户协议》</a>
</span>
</label>
</div>
<div class="user-form-item form-group">
<button type="submit" class="user-form-button" style="font-weight: bold;">立即注册</button>
</div>
</form>

</body>
</html>

3. 校验与短信 js

核心逻辑:

  • 校验手机号输入
  • 校验手机号符合规则 flag
  • 倒计时,显示秒
  • 计秒器不能为负数
  • 倒计时过程禁用按钮
  • 倒计时结束使能按钮,恢复计数器

smsAndValidator.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
var inter;
/**
* 发送验证码
*/
function sendSMS() {
//校验手机号,触发 bootstrapValidator 对手机号校验
//初始化 bootstrapValidator 对象
var validator = $("#myForm").data('bootstrapValidator');
validator.validateField("user_tel");
var flag = validator.isValidField("user_tel");
console.log(flag);
// 手机号被输入,且手机号规则符合正则才可以点击发送验证码
if (flag) {
//触发重复行为:每隔一秒显示一次数字
inter = setInterval("showCount()", 1000);
$(".qrcode").attr("disabled", true);

// 请求服务器发送验证码
$.post("${pageContext.request.contextPath}/sms", {
"methodName": "sendSMS",
"phoneNum": $("#user_tel").val()
}, function (data) {
console.log(data);
}, "json");
}
}

var count = 6; // 一般10或30或60s
function showCount() {
$(".qrcode").text(count + "S");
count--;
if (count < 0) {
clearInterval(inter);
$(".qrcode").text("发送验证码");
count = 6;
$(".qrcode").attr("disabled", false);
}
}

$(function () {
$("#myForm").bootstrapValidator({
message: "this is no a valiad field",
fields: {
user_tel: { // 手机号校验
message: "手机号格式错误",
validators: {
notEmpty: {
message: "手机号不能为空"
},
stringLength: {
message: "手机号长度为11",
min: 11,
max: 11
},
regexp: {
message: "手机号格式不对",
regexp: /^[1]{1}[1356789]{1}[0-9]+$/
}
}
},
user_password: {
message: "密码格式错误",
validators: {
notEmpty: {
message: "密码不能为空"
},
stringLength: {
message: "密码长度为6~8",
min: 6,
max: 8
},
regexp: {
message: "密码由小写字母、数字组成",
regexp: /^[a-z0-9]+$/
},
different: {
message: "密码不能和手机号一致",
field: "user_tel"
}
}
},
qrCode: { // 验证码输入框
message: "验证码格式错误",
validators: {
notEmpty: {
message: "验证码不能为空"
},
stringLength: {
message: "验证码长度为4",
min: 4,
max: 4
}
}
}
}
});
})

4. 工具类 SmsUtils

AccessKey 封装配置文件:

1
2
accessKeyId:xxxxx
accessKeySecret:xxxxx

将 阿里云 的短信发送 demo 封装为工具类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;

import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Random;

public class SmsUtil {
//产品名称:云通信短信API产品,开发者无需替换
static final String product = "Dysmsapi";
//产品域名,开发者无需替换
static final String domain = "dysmsapi.aliyuncs.com";

static final String accessKeyId ;
static final String accessKeySecret ;
static {
InputStream inputStream = SmsUtil.class.getClassLoader().getResourceAsStream("sms.properties");
Properties properties = new Properties();
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
accessKeyId = properties.getProperty("accessKeyId");
accessKeySecret = properties.getProperty("accessKeySecret");
System.out.println("accessKeyId=" + accessKeyId);
System.out.println("accessKeySecret=" + accessKeySecret);
}

/**
* 发送验证码
* @param session
* @return
* @throws ClientException
*/
public static SendSmsResponse sendSms(HttpSession session, String phoneNum) throws ClientException {

//可自助调整超时时间
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");

//初始化acsClient,暂不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);

//组装请求对象-具体描述见控制台-文档部分内容
SendSmsRequest request = new SendSmsRequest();
//必填:待发送手机号
request.setPhoneNumbers(phoneNum);
//必填:短信签名-签名名称, 可在短信控制台中找到
request.setSignName("签名名称");
//必填:短信模板-模版CODE, 可在短信控制台中找到
request.setTemplateCode("模板CODE");

//产生四位随机验证码
StringBuffer randomNum = new StringBuffer();
for (int i = 0; i < 4; i++) {
randomNum.append(new Random().nextInt(10));
}
request.setTemplateParam("{'code':"+randomNum+"}");
//四位随机验证码存储到session
session.setAttribute("phoneVarificationCode", randomNum);

//hint 此处可能会抛出异常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
return sendSmsResponse;
}
}

5. 资源调用 Servlet

SmsServlet.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@WebServlet(name = "SmsServlet", urlPatterns = "/sms")
public class SmsServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String methodName = request.getParameter("methodName");
if (methodName.equals("sendSMS")) {
String qrCode = request.getParameter("qrCode");
String user_tel = request.getParameter("user_tel");
try {
// 发送短信 --> 手机接收验证码
SendSmsResponse sendSmsResponse = SmsUtil.sendSms(request.getSession(), user_tel);
System.out.println(sendSmsResponse.getMessage());
// code 和 message 为 OK 时,可以确定验证码发送成功
if (sendSmsResponse.getCode().equals("OK") && sendSmsResponse.getMessage().equals("OK")) {
// 从 session 域中获取验证码
String phoneVarificationCode = (String) request.getSession().getAttribute("phoneVarificationCode");
if (qrCode.equals(phoneVarificationCode)) {
System.out.println("验证码验证成功,存储注册信息到数据库...");
}
}
} catch (ClientException e) {
e.printStackTrace();
}
}
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}

02-手机短信验证码
https://janycode.github.io/2018/05/13/04_网页技术/10_验证码技术/02-手机短信验证码/
作者
Jerry(姜源)
发布于
2018年5月13日
许可协议