实现图片验证码与手机短信验证码

实现图片验证码与手机短信验证码:

 

1、HTML 代码:


<!-- 和验证码一样大小的提示图片:"请输入手机号" -->
    <input type="hidden" value="${@cn.mycs.core.util.ToolUtil.url(@cn.mycs.core.constant.CommonConstant.DOMAINS_STATIC)}/2.0.0/images/safeCode.jpg" id="tipImageUrl">
<div class="form-group">
                            <label for="" class="control-label col-sm-3">联系人手机:</label>
                            <div class="col-sm-9">
                                <input maxlength="11" name="phone" placeholder="负责人手机" data="手机号码" warn="请输入11位数的手机号!" data-options="required:true" type="text" class="form-control easyui-validatebox" id="phone2">
                                <span class="reg_warn" style="color: red;"></span>
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="" class="control-label col-sm-3">验证码:</label>
                            <div class="col-sm-9">
                                <div class="row">
                                    <div class="col-sm-4">
                                        <input name="safeCode" id="safeCode2"  maxlength="4"  data="验证码" warn="4位字符的验证码!" type="text" data-options="required:true,tipPosition:'left'" class="form-control easyui-validatebox">
                                    </div>
                                    <div class="col-sm-4">
                                        <img class="validate-img"  src="${@cn.mycs.core.util.ToolUtil.url(@cn.mycs.core.constant.CommonConstant.DOMAINS_STATIC)}/2.0.0/images/safeCode.jpg" id="validate-img2" />
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="" class="control-label col-sm-3">短信验证码:</label>
                            <div class="col-sm-9">
                                <div class="row">
                                    <div class="col-sm-4">
                                        <input name="smsCodeM" maxlength="6"  placeholder="6位验证码" data="手机验证码"   warn="请输入手机验证码!"  type="text" class="form-control  easyui-validatebox" />
                                        <span class="reg_warn" style="color: red;"></span>
                                    </div>
                                    <div class="col-sm-8">
                                        <button type="button" class="btn btn-primary" id="big_gray_btn2">发送验证码</button>
                                    </div>
                                </div>
                            </div>
                        </div>

2、js代码:

//手机号输入事件
    $("input[name='phone']").keyup(function () {
        var _this = $(this), v = _this.val(), obj_safeCode = _this.parent().parent().next("div").find(".validate-img");
        if (_this.data("v") != v) {
            _this.data("v", v);
            /^1\d{10}$/.test(v) ? obj_safeCode.trigger("click") : obj_safeCode.attr("src", $("#tipImageUrl").val());
        }
    });
    //验证码点击事件
    $("#validate-img1").click(function () {
        var error = $(".reg_error");
        for (var i = 0; i < error.length; i++) {
            if (error.eq(0 + "").html()=="该手机号已被绑定") {
                return;
            }
        }
        var v = $("#phone1").val();
        $(this).parent().prev("div").find("input[name='safeCode']").val("");
        /^1\d{10}$/.test(v) && $(this).attr("src", _ctx + "/validateCode?refresh=" + Math.random());
    });

//发送(手机|邮箱)验证码
    $("#big_gray_btn1").click(function () {
        var error = $(".reg_error");
        for (var i = 0; i < error.length; i++) {
            if (error.eq(0 + "").html()=="该手机号已被绑定") {
                alert("该手机号已被绑定","error");
                return;
            }
        }
        var _this = $(this), txt = _this.text(), div = _this.closest("div");
        if (txt == "发送验证码") {
            var tel_input = $("#phone1");
            var safeCode = $("#safeCode1").val();
            var tel_mess = tel_input.parent().nextAll("span").text();
            var tel = tel_input.val();
            if (tel_mess == "该号码已被绑定") {
                alert("请重新输入手机号码", "error");
            } else if (!/^[a-zA-Z0-9]{4}$/.test(safeCode)) {
                alert("请先输入正确的验证码!", "error");
            } else if (/^1\d{10}$/.test(tel)) {
                _this.text("请稍候……");
                _this.nextAll("span").hide();
                $.getJSON(_ctx + "/app/mobileSms?action=send&captchaCode=" + safeCode + "&phone=" + tel + "&" + Math.random(), function (json) {
                    _this.text(txt);
                    if (1 != json.code) {
                        alert(json.message, "error");
                        if (json.message == "图形验证码错误") {
                            $("#validate-img1").click();
                        }
                    } else {
                        setT(_this, 180, txt);
                        div.nextAll("span").text("此手机验证码30分钟内有效").attr({"class": "reg_warn"}).show();
                    }
                });
            } else {
                div.css("border-color", "#dedede").nextAll("span").text("请先输入正确的手机号!").attr({"class": "reg_warn"});
                tel_input.focus().parent().css("border-color", "#f77979").nextAll("span").attr("class", "reg_error");
            }
        }
    });

3、发送短信 控制器 Controller:

package cn.wpg.client.web.controller.persional;

import cn.wpg.core.base.restful.JsonResult;
import cn.wpg.core.constant.MobileProperties;
import cn.wpg.core.support.StrKit;
import cn.wpg.core.util.MobileSmsUtil;
import cn.wpg.server.persistence.redis.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Random;


/**
 * <p>发送短信 控制器 Controller</p>
 * <pre>
 * @author Wupeiguo
 * @date 2019/06/14 11:42
 * </pre>
 */
@Controller
public class MobileSmsController {
    private final Logger log = LoggerFactory.getLogger(getClass());
    @Autowired
    private RedisService redisService;

    @RequestMapping("/app/mobileSms")
    @ResponseBody
    public JsonResult mobileSms(String action, String captchaCode, String phone, HttpServletRequest request) {
        if (StrKit.isEmpty(action) || StrKit.isEmpty(phone)) {
            log.debug("参数错误");

            return JsonResult.error("参数错误");
        }

        //获取redis 图形验证码做校验
        String code = redisService.get("cookiesReplyKey", 8, String.class);
        if (StrKit.isEmpty(code)) {
            log.debug("请重新获取图形验证码");
            return JsonResult.error("请重新获取图形验证码");
        } else if (!code.equalsIgnoreCase(captchaCode)) {
            log.debug("图形验证码错误");
            return JsonResult.error("图形验证码错误");
        } else if ("sendCode".equals(action)) {
            return sendCode(phone);
        }
        return JsonResult.success("发送成功");
    }

    private JsonResult sendCode(String phone) {
        log.debug("发送手机验证码");
        String key = "smsCode_" + phone;
        Object redisCode = redisService.get(key, Object.class);
        if (redisCode != null) {
            log.info("稍后再试");
            return JsonResult.error("稍后再试");
        }
        //生成随机号码
        final String smsCode = getRandomCode();
        //发送短信验证码
        JsonResult result = MobileSmsUtil.send(MobileProperties.SMS_APPID, phone, MobileProperties.SMS_TEMPLATEID, smsCode, "json");
        if (result.getCode() == 1) {
            redisService.set(key, smsCode, 120);
            log.info("发送短信验证码成功");
            return JsonResult.success("发送成功");
        } else {
            log.info("发送短信验证码失败");
            return JsonResult.error("发送失败");
        }
    }

    /***
     * 生成随机号码 6位
     * @return
     */
    private String getRandomCode() {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();

    }
}

4、发送短信相关的配置 Properties:

package cn.wpg.core.constant;

import cn.wpg.core.util.MD5Util;

import java.util.Base64;
import java.util.Date;


/**
 * <p>发送短信相关的配置 Properties</p>
 * <pre>
 * @author Wupeiguo
 * @date 2019/06/14 11:42
 * </pre>
 */
public class MobileProperties {

    /**
     * API请求地址
     */
    private static final String SMS_BASE_URL = "https://api.XXX.com/";
    /**
     * 云之讯REST API版本号。当前版本号为:2014-06-30
     */
    private static final String SMS_SOFTVERSION = "2014-06-30";
    /**
     * 开发者账号ID。由32个英文字母和阿拉伯数字组成的开发者账号唯一标识符。
     */
    private static final String SMS_ACCOUNT_SID = "96ea71afc8a76e978cbc13f67a4aa624";
    /**
     * 开发者账号TOKEN
     */
    private static final String SMS_TOKEN = "c59ff426f4c88a2dc0e612a6c860b144";
    private static String timestamp;

    public static final String SMS_APPID = "5edd47ba7fa84465a90c1d08ac8c9547";
    public static final String SMS_TEMPLATEID = "51730";

    /**
     * @return string
     * 验证参数,URL后必须带有sig参数,sig= MD5(账户Id + 账户授权令牌 + 时间戳,共32位)(注:转成大写)
     */
    private static String getSigParameter() {
        String sig = SMS_ACCOUNT_SID + SMS_TOKEN + timestamp;
        sig = MD5Util.encrypt(sig);
        return sig.toUpperCase();
    }

    private static String getTimestamp() {
        return format(new Date(), "yyyyMMddHHmmss");
    }

    public static String getSendSmsUrl() {
        timestamp=getTimestamp();
        return SMS_BASE_URL + SMS_SOFTVERSION + "/Accounts/" + SMS_ACCOUNT_SID + "/Messages/templateSMS?sig=" + getSigParameter();
    }

    public static String getAuthorization() {
        String data = SMS_ACCOUNT_SID + ":" + timestamp;
        return Base64.getEncoder().encodeToString(data.getBytes());
    }

    /**
     * 根据特定格式格式化日期
     *
     * @param date   被格式化的日期
     * @param format 格式
     * @return 格式化后的字符串
     */
    public static String format(Date date, String format) {
        return new SimpleDateFormat(format).format(date);
    }

}
 

5、手机发送短信工具 Util:

package cn.wpg.core.util;

import cn.wpg.core.base.restful.JsonResult;
import cn.wpg.core.constant.MobileProperties;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;


/**
 * <p>手机发送短信工具 Util</p>
 * <pre>
 * @author Wupeiguo
 * @date 2019/06/14 11:42
 * </pre>
 */
public class MobileSmsUtil {
    public static JsonResult send(String appId, String phone, String templateId, String smsCode, String type) {
        String sendSmsUrl = MobileProperties.getSendSmsUrl();
        String body;
        if ("json".equals(type)) {
            JSONObject json = new JSONObject();
            Map<String, String> bodyMap = new HashMap<>(4);
            bodyMap.put("appId", appId);
            bodyMap.put("templateId", templateId);
            bodyMap.put("appId", appId);
            bodyMap.put("to", phone);
            bodyMap.put("param", smsCode);

            json.put("templateSMS", bodyMap);
            body = json.toJSONString();
        } else if ("xml".equals(type)) {
            String bodyXml = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" +
                    "<templateSMS>" +
                    "<templateId>" + templateId + "</templateId>" +
                    "<to>" + phone + "</to>" +
                    "<param>" + smsCode + "</param>" +
                    "<appId>" + appId + "</appId>" +
                    "</templateSMS>";
            body = bodyXml;
        } else {
            throw new RuntimeException("只能json或xml,默认为json");
        }
        String result = doSend(sendSmsUrl, body, type);
        return result == null ?JsonResult.error("发送失败"):JsonResult.success(result);
    }

    private static String doSend(String url, String body, String type) {
        String mine;
        if ("json".equals(type)) {
            mine = "application/json";
        } else {
            mine = "application/xml";
        }
        Map<String, String> header = new HashMap<>(3);
        header.put("Accept", mine);
        header.put("Content-Type", mine + ";charset=utf-8");
        header.put("Authorization", MobileProperties.getAuthorization());
        return HdoPost(url, body, header);
    }


    private static String HdoPost(String url, String body, Map<String, String> header) {
        HttpClient httpClient;
        HttpPost postMethod;
        HttpResponse response;
        try {
            httpClient = HttpClients.createDefault();
            //传入URL地址
            postMethod = new HttpPost(url);
            //设置请求头
            if (header != null) {
                for (Map.Entry<String, String> entry : header.entrySet()) {
                    //设置请求头
                    postMethod.addHeader(entry.getKey(), entry.getValue());

                }
            }
            // 传入请求参数
            postMethod.setEntity(new StringEntity(body, Charset.forName("UTF-8")));
            // 获取响应
            response = httpClient.execute(postMethod);
            int statusCode = response.getStatusLine().getStatusCode();
            System.out.println("HTTP Status Code:" + statusCode);
            if (statusCode != HttpStatus.SC_OK) {
                System.out.println("HTTP请求未成功!HTTP Status Code:" + response.getStatusLine());
                return null;
            }
            HttpEntity httpEntity = response.getEntity();
            String reponseContent = EntityUtils.toString(httpEntity);
            // 释放资源
            EntityUtils.consume(httpEntity);
            System.out.println("响应内容:" + reponseContent);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
}

 

6、MD5加密类(封装jdk自带的md5加密方法):

package cn.wpg.core.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5加密类(封装jdk自带的md5加密方法)
 * @author zhangzhc 
 * @date 2018-06-07 10:57:38
 */
public class MD5Util {

    /**
     * 安全码
     */
    public static final String SECURITY_CODE = "wha3202343222dxssssssswwd";
    
    /**
     * md5加密密码
     *
     * @param source 源数据
     * @param salt   盐
     * @return String
     */
    public static String encryptAndSalt(String source, String salt) {
        salt = (salt != null ? salt : "") + SECURITY_CODE;
        source = MD5Util.encrypt(source) + salt;
        return MD5Util.encrypt(source);
    }

    /**
     * md5加密
     *
     * @param source 源数据
     * @return String
     */
    public static String encrypt(String source) {
        return encodeMd5(source.getBytes());
    }

    private static String encodeMd5(byte[] source) {
        try {
            return encodeHex(MessageDigest.getInstance("MD5").digest(source));
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private static String encodeHex(byte[] bytes) {
        StringBuffer buffer = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            if (((int) bytes[i] & 0xff) < 0x10) {
                buffer.append("0");
            }
            buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
        }
        return buffer.toString();
    }

    public static void main(String[] args) {
        System.out.println(encrypt("123456"));
    }
}

7、备注:

jar包:

com.alibaba.fastjson:
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>${fastjson.version}</version>
</dependency>

org.apache.http:
<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-http</artifactId>
</dependency>

结果类 JsonResult:

该操作结果类为自定义类,可以用  Object 类型替代

获取图形验证码:

在《图形验证码》篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wpg_boke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值