0%

如何使用短信验证码完成注册功能

一. MD5加密工具类

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

/**
 * 密码加密工具
 */
public class Md5Utils {

    /**
     * 加密
     * @param context
     */
    public static String encrypByMd5(String context) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(context.getBytes());//update处理  
            byte [] encryContext = md.digest();//调用该方法完成计算  

            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < encryContext.length; offset++) {//做相应的转化(十六进制)  
                i = encryContext[offset];
                if (i < 0) i += 256;
                if (i < 16) buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            return buf.toString();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block  
            e.printStackTrace();
            return  null;
        }
    }
  }

二. 短信服务

短信验证,只有三大运营商具有短信发送的能力。要发送短信只有找三大运营,或者中间商。简单说就是要找第三方的短信平台。常见的有阿里云,京东智联云,乐讯通等等非常多。举例使用网建短信通:http://www.smschinese.cn/

  1. 操作流程

    点击左上角首页 -> API接口 -> 网建SMS短信通API接口地址 -> UTF-8编码发送短信接口:
    http://utf8.api.smschinese.cn/?Uid=本站用户名&Key=接口短信密钥&smsMob=手机号码&smsText=验证码:8888
        本站用户名Uid:注册时用户名
        接口安全密钥key:刚刚看到的密钥
        手机号码smsMob:手机号码
        短信内容smsText:随便写
    api接口中有发送短信的各个对应状态:发送了一条,就只剩下4条了
    
  2. 导入依赖

          <!-- 主要用于后端发送http请求-->
            <!-- 后端发送http请求 - 一般用在调用三方接口时会用 -->
            <dependency>
                <groupId>commons-httpclient</groupId>
                <artifactId>commons-httpclient</artifactId>
                <version>3.1</version>
            </dependency>
    
  3. 发送短信工具类(官网也有相应代码可参考)

    
    package io.coderyeah.basic.util;
    
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.NameValuePair;
    import org.apache.commons.httpclient.methods.PostMethod;
    
    /**
     * 短信发送工具类
     */
    public class SmsUtils {
    
        //用户名
        public static final String UID = "codermyth";
        //秘钥
        public static final String KEY = "29766C0677741B5DA2CE2203260365DB";
    
        /**
         * 发送短信
         *
         * @param phones  手机们 a,b
         * @param content 发送内容
         * @return 返回值
         */
        public static String sendSms(String phones, String content) {
            PostMethod post = null;
            try {
                HttpClient client = new HttpClient();
                post = new PostMethod("http://utf8.api.smschinese.cn");
                post.addRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf8");//在头文件中设置转码
                NameValuePair[] data = {new NameValuePair("Uid", SmsUtils.UID),
                        new NameValuePair("Key", SmsUtils.KEY),
                        new NameValuePair("smsMob", phones),
                        new NameValuePair("smsText", content)};
                post.setRequestBody(data);
    
                client.executeMethod(post);
                int statusCode = post.getStatusCode();
                System.out.println("statusCode:" + statusCode); //200 404 400
                String result = new String(post.getResponseBodyAsString().getBytes("utf8"));
                return result;
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (post != null) {
                    post.releaseConnection();
                }
            }
            return null;
        }
    
        public static void main(String[] args) {
            System.out.println(SmsUtils.sendSms("18365403510", "您的验证码为:【8848】,鉴于您优秀的能力表现,您被授予玛丽叶奥特曼称号,accept it, cutie!"));
        }
    }
    

三. 前端获取验证码接口

 <div class="verification">
     <label for="code"><i class="am-icon-code-fork"></i></label>
          <input type="tel" name="" id="code" v-model="phoneUserForm.phoneCode"  placeholder="请输入验证码">
               <button type="button" id="dyMobileButton" @click="sendMobileCode">获取验证码</button>
 </div>

获取短信验证码

// 发送验证码
sendMobileCode() {
    //1.判断手机号不为空
    if (!this.phoneUserForm.phone) {
        alert("手机号不能为空");
        return;
    }
    //2.判断图片验证码不为空
    if (!this.phoneUserForm.imageCode) {
        alert("图片验证码不能为空");
        return;
    }
    //3.获取按钮,禁用按钮  发送时灰化不能使用,发送成功倒计时60才能使用,如果发送失败立即可以发送
    let sendBtn = $(event.target);
    sendBtn.attr("disabled", true);

    let param = {
        phone: this.phoneUserForm.phone,
        imageCode: this.phoneUserForm.imageCode,
        imageCodeKey: localStorage.getItem("verifyCodeKey")
    };

    //4.发送ajax请求
    this.$http.post("/verifyCode/smsCode", param).then(res => {
        const ajaxResult = res.data;
        if (ajaxResult.success) {
            alert("手机验证码已经发送到您的手机,请在3分钟内使用");
            //4.1.发送成:倒计时
            let time = 60;
            let interval = window.setInterval(function () {
                //每一条倒计时减一
                time = time - 1;
                //把倒计时时间搞到按钮上
                sendBtn.html(time + 's');
                //4.2.倒计时完成恢复按钮
                if (time <= 0) {
                    sendBtn.html("重新发送");
                    sendBtn.attr("disabled", false);
                    //清除定时器
                    window.clearInterval(interval);
                }
            }, 1000);
        } else {
            //4.3.发送失败:提示,恢复按钮
            sendBtn.attr("disabled", false);
            alert(ajaxResult.msg);
        }
    })
}

发送请求

//手机注册功能
            phoneRegister() {
                if (!this.agree) {
                    alert('请勾选服务协议')
                    return;
                }
                //前台一般做校验:空校验,格式校验,重复密码校验
                this.$http.post('/user/register/phone', this.phoneUserForm).then(res => {
                    //注册成功跳转到登录页面
                    if (res.data.success) {
                        location.href = "login.html";
                    } else {
                        alert(res.data.msg);
                    }
                }).catch(res => {
                    alert("系统错误!")
                });
            },

四. 后端实现获取短信接口

 @PostMapping("/smsCode")
    @ApiOperation("获取短信验证码")
    public Result getPhoneCode(@RequestBody PhoneCodeDTO phoneCodeDTO) {
        try {
            return verifyCodeService.getPhoneCode(phoneCodeDTO);
        } catch (BusinessException e) {
            e.printStackTrace();
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            return Result.fail("系统异常,请稍后重试!");
        }
    }
 @Override
    public Result getPhoneCode(PhoneCodeDTO phoneCodeDTO) {
        final String phone = phoneCodeDTO.getPhone();
        final String InputImageCode = phoneCodeDTO.getImageCode();
        final String imageCodeKey = phoneCodeDTO.getImageCodeKey();
        // 1.判断参数是否为空
        if (StrUtil.isBlank(phone)) {
            // 抛出异常
            throw new BusinessException("电话号码不能为空");
        }
        if (StrUtil.isBlank(InputImageCode)) {
            // 抛出异常
            throw new BusinessException("图形验证码不能为空不能为空");
        }
        // 2.判断图形验证码是否过期 正确
        final String imageCode = stringRedisTemplate.opsForValue().get("cache:code:image:" + imageCodeKey);
        if (StrUtil.isBlank(imageCode)) {
            // 过期了
            throw new BusinessException("图形验证码已过期,请重新输入!");
        }
        // 判断是否一致 忽略大小写
        if (!InputImageCode.equalsIgnoreCase(imageCode)) {
            throw new BusinessException("图片验证码错误,请重新输入!");
        }
        // 3. 通过号码判断用户是否已经注册
        final User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
        if (user != null) {
            // 用户已经存在
            throw new BusinessException("该手机号码已被注册过,请您直接登录...");
        }
        // 4.从redis获取短信验证码
        // 用来存储短信验证码  redis中存储的值是 【短信验证码:时间戳】
        String code = null;
        final String value = stringRedisTemplate.opsForValue().get(Constants.USER_REGISTER_PHONE_PREFIX + phone);
        if (value != null) { // 没有过期
            // 判断时间是否过期
            final long oldTime = Long.parseLong(value.split(":")[1]);
            // 一分钟之内不允许频繁操作
            if ((System.currentTimeMillis() - oldTime) <= 1000 * 60) {// 没过重发时间
                throw new BusinessException("操作频繁,请稍后再试!");
            } else {
                code = value.split(":")[0];
            }
        } else {// 过期了
            // 生成验证码
            code = String.valueOf(RandomUtil.randomNumbers(6));
        }
        // 存入redis 有效期3分钟
        stringRedisTemplate.opsForValue().set("user:register:" + phone, code + ":" + System.currentTimeMillis(), 3L, TimeUnit.MINUTES);
        // 发送验证码短信
//        SmsUtils.sendSms(phone, "您的验证码是" + code + ",请及时使用有限期为3分钟");
        log.info("=========您的验证码是:{}=========", code);
        return Result.success("获取验证码成功【" + code + "】");
    }
-------------本文结束感谢您的阅读-------------
you can reward me here. Thank you!

欢迎关注我的其它发布渠道