版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qiyongkang520/article/details/55007040
在上一篇博文中,给大家介绍了图片验证码的实现,今天再给大家介绍一下手机短信验证码的实现。其实,这个和图片验证码差不多,只不过要把后天生成的验证码发到对应的手机号码上,然后再进行验证。这里,关于发短信的功能可以找手机短信服务商,对接相应的接口即可。
好了,笔者就直接贴出相应的代码,流程也比较简单,第一步就是生成验证码发到对应的手机上,把相关数据放在session或内存中,第二步就是验证了。
一、html代码
这里做了一个比较简洁的html页面模拟大致的过程,代码如下:
<!DOCTYPE html>
<html>
<head>
<title>图片验证码</title>
<meta charset="utf-8"/>
</head>
<body>
<label>手机号码</label><input id="mobile" name="mobile" type="tel" placeholder="请输入手机号码"/>
<br />
<button type="button" id="yzm_btn">获取验证码</button>
<hr />
<label>验证码</label><input id="yzm" name="yzm" type="number" placeholder="请输入4位数验证码"/>
<span id="remainTime">30s</span> <button type="button" id="recapture_btn" style="display:none;">重新获取验证码</button>
<br />
<button type="button" id="check_btn">验证</button>
<script src="/m/plugins/zepto/zepto.min.js" type="text/javascript"></script>
<script src="../../scripts/captcha/mobileCode.js" type="text/javascript"></script>
</body>
</html>
页面展示如下:
二、js代码
js代码逻辑如下,这里就是发送和验证了,代码如下:
/**
* 手机验证码
*/
var mobile = '';
var count = 30; //验证码 有效期 30s
var curCount = 0; //当前剩余秒数 开始为0
var InterValObj = "";
$(function() {
console.log('获取手机验证码。。。');
//获取验证码
$('#yzm_btn').click(function() {
//获取手机号
mobile = $('#mobile').val();
console.log('mobile:', mobile);
if (mobile.trim().length == 0) {
alert('手机号不能为空。。。');
} else {
sendYzm();
}
});
//重新获取验证码
$('#recapture_btn').click(function() {
sendYzm();
});
//验证
$('#check_btn').click(function() {
var mbCode = $('#yzm').val();
var timing = $("#remainTime").text();
if(timing == '0s') {
alert("验证码过期请重新获取");
return ;
} else if (mbCode == "" && mbCode.length<1){
alert("验证码不能为空");
return ;
} else {
//拦截器验证短信验证码
var afterSendMobileCode = function(data) {
alert(data.msg)
if(data.success){
//停止计时
window.clearInterval(InterValObj);
}
};
$.post('/sys/mobileCode/validateMobileCode.do', {"mobile":mobile, "vCode":mbCode}, afterSendMobileCode);
}
});
});
/*
* 计时器
*/
function getCode() {
window.clearInterval(InterValObj);//停止计时器
curCount = count;
InterValObj = window.setInterval(setRemainTime, 1000); //启动计时器,1秒执行一次
}
/*
* 更新剩余时间
*/
function setRemainTime() {
if (curCount == 1) {
window.clearInterval(InterValObj);//停止计时器
alert("验证码过期,请重新获取");
$('#remainTime').hide();
$('#recapture_btn').show();
} else {
curCount--;
$("#remainTime").html(curCount + "s");
}
}
/**
* 发送验证码
*/
function sendYzm() {
//发送验证码
var param = {
mobile: mobile
}
$.post('/sys/mobileCode/sendMobileCode.do', param, function(data) {
console.log('data:', data);
alert(data.msg);
if (data.success) {
//启动定时器
getCode();
}
});
}
三、发送短信以及验证
由于短信服务是需要收费,这里就没有对接短信服务提供商,到时真正要使用此功能的时候,再由客服公司购买此服务。相应的验证码生成发送以及验证逻辑如下:
/**
* Project Name:qyk_testSpringMVC
* File Name:MobileCodeController.java
* Package Name:com.qiyongkang.sys.controller
* Date:2017年2月9日下午10:28:44
* Copyright (c) 2017, Thinkive(http://www.thinkive.com/) All Rights Reserved.
*
*/
package com.qiyongkang.sys.controller;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.qiyongkang.sys.dto.ExtJsObject;
/**
* ClassName:MobileCodeController <br/>
* Function: 手机验证码. <br/>
* Date: 2017年2月9日 下午10:28:44 <br/>
*
* @author qiyongkang
* @version
* @since JDK 1.6
* @see
*/
@Controller
@RequestMapping
public class MobileCodeController {
/**
* 日志类
*/
private static Logger logger = LogManager.getLogger(MobileCodeController.class);
// 验证码过期时间,秒
private float LIMIT_TIME = 30.0f;
private static Map<String, Integer> sendNumMap = new HashMap<String, Integer>();
private static Map<String, Long> sendTimeMap = new HashMap<String, Long>();
public static Map<String, String> mobilevcodeMap = new HashMap<String, String>();
private static int sentTime = 3; // 短信限制的次数
private static int CODE_LENGTH = 4; // 验证码长度
/**
*
* sendMobileCode: 发送手机验证码. <br/>
*
* @author qiyongkang
* @param request
* @return
* @since JDK 1.6
*/
@RequestMapping
@ResponseBody
public ExtJsObject sendMobileCode(HttpServletRequest request) {
ExtJsObject extJsObject = new ExtJsObject();
// session
HttpSession session = request.getSession();
// 获取手机号
String mobile = request.getParameter("mobile");
logger.info("开始发送手机验证码。。。");
// 验证是否重复发送
long checkTime = new Date().getTime();
if (sendNumMap.size() > 0 && sendNumMap.get(mobile) != null) {
float btTime = (checkTime - sendTimeMap.get(mobile)) / 1000;
// 检测是否频繁发送
if (btTime < LIMIT_TIME) {
extJsObject.setSuccess(false);
extJsObject.setMsg("获取验证码频繁,请稍后再获取");
return extJsObject;
}
// 当天发送短信条数的限制
int number = sendNumMap.get(mobile);
if (number == sentTime) {
extJsObject.setSuccess(false);
extJsObject.setMsg("每个号码每天只能获取" + sentTime + "次注册验证码");
return extJsObject;
}
}
// 生成验证码和发送的短信内容
String code = getCode();
String content = "您的验证码为:" + code + ",温馨提示:如非本人操作,请忽略此短信!";
/* 发送短信给此手机号, 这里看对接哪家短信服务提供商 */
boolean result = sendMessage(mobile, content);
logger.warn("您的验证码为:" + code + ", 温馨提示:如非本人操作,请忽略此短信!");
if (result) {
// 将认证码存入SESSION
long createTime = new Date().getTime();
// 把验证码和手机号,生成时间绑定
session.setAttribute("@vcode", mobile + "|" + code + "|" + createTime);
logger.info("@@@是否存入了验证码信息:" + session.getAttribute("@vcode"));
logger.info("@@@获取验证码session:" + session.getId());
// 记录短信验证码
mobilevcodeMap.put(mobile, code);
// 记录发送验证码时间
sendTimeMap.put(mobile, createTime);
// 记录同一号码发送次数
Integer num = sendNumMap.get(mobile);
if (num == null) {
sendNumMap.put(mobile, 1);
} else {
sendNumMap.put(mobile, ++num);
}
extJsObject.setSuccess(true);
extJsObject.setMsg("发送成功!");
return extJsObject;
} else {
session.removeAttribute("@vcode");
extJsObject.setSuccess(false);
extJsObject.setMsg("发送失败!");
return extJsObject;
}
}
/**
*
* sendMessage: 发送短信的逻辑. <br/>
*
* @author qiyongkang
* @param mobile
* @param content
* @return
* @since JDK 1.6
*/
private boolean sendMessage(String mobile, String content) {
// 发送短信的逻辑
return true;
}
/**
*
* validateMobileCode: 校验手机验证码. <br/>
*
* @author qiyongkang
* @param request
* @return
* @since JDK 1.6
*/
@RequestMapping
@ResponseBody
public ExtJsObject validateMobileCode(HttpServletRequest request) {
ExtJsObject extJsObject = new ExtJsObject();
logger.info("验证短信");
// 获取手机号 和验证码
String mobile = request.getParameter("mobile");
String userCode = request.getParameter("vCode");
// 从session获取验证信息
HttpSession session = request.getSession();
String codeAndTime = (String) session.getAttribute("@vcode");
logger.info("@@@校验验证码,获取到的codeAndTime=" + codeAndTime);
logger.info("@@@校验验证码,session为" + session.getId());
if (StringUtils.isEmpty(codeAndTime)) {
extJsObject.setSuccess(false);
extJsObject.setMsg("验证码不能为空");
return extJsObject;
}
long checkTime = new Date().getTime();
// 如果超时验证不通过
float btTime = (checkTime - sendTimeMap.get(mobile)) / (1000);
// 如果超时验证不通过
if (LIMIT_TIME < btTime) {
extJsObject.setSuccess(false);
extJsObject.setMsg("验证码过期,请重新获取");
return extJsObject;
} else {
String sessionMobile = codeAndTime.split("\\|")[0];
String vcode = mobilevcodeMap.get(mobile);
// 判断输入手机号码和获取验证码手机号码是否一致
if (!sessionMobile.equals(mobile)) {
extJsObject.setSuccess(false);
extJsObject.setMsg("手机号码修改后,请重新获取短信验证码");
return extJsObject;
} else if (vcode.equals(userCode.trim())) {
extJsObject.setSuccess(true);
extJsObject.setMsg("验证成功!");
return extJsObject;
} else {
extJsObject.setSuccess(false);
extJsObject.setMsg("验证码输入错误,请重新输入");
return extJsObject;
}
}
}
/**
*
* getCode: 生成验证码. <br/>
*
* @author qiyongkang
* @return
* @since JDK 1.6
*/
public String getCode() {
String random = "";
while (true) {
random = (Math.random() * 10000) + "";
if (!StringUtils.isEmpty(random) && random.contains(".")) {
String[] randoms = random.split("\\.");
random = randoms[0];
}
if (random.length() >= CODE_LENGTH) {
break;
}
}
return random;
}
}
好了,关于手机验证码就介绍到这儿了。后面,笔者应该再不会写前端相关的博文了,因为现在笔者学的东西太杂了,没有一个学得比较好的。后面笔者打算专门学习java相关的技术,然后再和大家一起分享交流。