H5学习之路-手机短信验证码的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 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相关的技术,然后再和大家一起分享交流。

猜你喜欢

转载自blog.csdn.net/qiyongkang520/article/details/55007040