集成榛子云与Reids实现验证码登录

发布时间:2024年01月15日

效果:60秒内校验手机验证码

步骤1:前端页面vue2+ElementU

<template>
  <div>
    <el-form :model="formInline" :rules="rules" ref="formInline" class="demo-form-inline" label-width="90px">
      <el-form-item label="手机号" prop="authPhone">
        <el-input v-model="formInline.authPhone" placeholder="请输入手机号" style="width: 360px"></el-input>
      </el-form-item>
      <el-form-item label="验证码" prop="authCode">
        <el-input v-model="formInline.authCode" placeholder="请输入验证码" style="width: 180px"></el-input>
        <el-button type="primary" @click="handleSend" :disabled="disable">{{ text }}</el-button>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="submitForm('formInline')">登录</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

步骤2:使用定时器禁用按钮

<script>
export default {
  data() {
    return {
      text: '发送验证码',//按钮显示
      time: 60,//设置按钮时间,即验证码时间
      timer: null,//定时器
      disable: false,//是否禁用
      formInline: {authPhone: "", authCode: ""},
      rules: {
        authPhone: [
          {required: true, message: '请输入手机号', trigger: 'blur'},
        ], authCode: [
          {required: true, message: '请输入验证码', trigger: 'blur'},
        ],
      }
    }
  }, methods: {
    handleSend() {
      //校验手机号格式
      let regTel = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
      if (!regTel.test(this.formInline.authPhone)) {
        this.$message.error("请输入正确的手机号格式");
        return false;
      }
      axios.post("http://localhost:8101/auth/sendCode?phone=" + this.formInline.authPhone).then(() => {
        //按钮开启禁用
        this.disable = true
        //提示剩余时间
        this.text = this.time + 's后重新发送'
        //启用定时器
        this.timer = setInterval(() => {
          //如果时间不为0,那么显示剩余时间,如果结束显示重新发送
          if (this.time > 0) {
            this.time--
            this.text = this.time + 's后重新发送'
          } else {
            //停止定时器
            clearInterval(this.timer)
            this.time = 60
            this.disable = false
            this.text = '重新发送'
          }
        }, 1000)
      })
    }, submitForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          axios.post("http://localhost:8101/auth/loginByCode", this.formInline).then(r => {
            // noinspection JSCheckFunctionSignatures
            setCookie("token", r.data.data);
            this.$router.push("list");
          })
        } else {
          console.log('error submit!!');
          return false;
        }
      });
    }
  }, created() {
    const time = localStorage.getItem('time')
    if (time && time > 0) {
      this.text = time + 's后重新发送'
      this.time = time
      this.handleSend()
    }
  }
}
</script>

步骤3:使用榛子云发送短信

    /**
     * 获取验证码
     */
    @RequestMapping("sendCode")
    public R sendCode(@RequestParam("phone") String phone) {
        // 随机生成6位数验证码
        String code = RandomUtil.randomString("1234567890", 6);
        // 查询是否已存在验证码,如果未存在验证码则发送验证码
        if (!redisTemplate.hasKey("key-" + phone)) {
            // 获取榛子云客户端
            ZhenziSmsClient client = new ZhenziSmsClient(MyConfig.appUrl, MyConfig.appId, MyConfig.appSecret);
            // 构建参数集合
            HashMap<String, Object> map = new HashMap<>();
            // 接收到短信的手机号
            map.put("number", phone);
            // 榛子云短信模板"2"
            map.put("templateId", MyConfig.templateIdTwo);
            // 新建长度为"1"的数组
            String[] templateParams = new String[1];
            // 为第"1"个参数,赋值
            templateParams[0] = code;
            // 榛子云短信模板"2"参数
            map.put("templateParams", templateParams);
            try {
                // 发送短信
                String send = client.send(map);
            } catch (Exception e) {
                // 发送失败
                return R.failed("验证码发送失败");
            }
            // 将验证码存入redis,设置结束时间为60秒
            redisTemplate.opsForValue().set("key-" + phone, code, 60, TimeUnit.SECONDS);
            // 短信发送成功
            return R.successed("验证码发送成功");
        } else {
            // 获取剩余时间
            Long expireTime = redisTemplate.getExpire("key-" + phone);
            return R.failed("验证码已发送,请" + expireTime + "秒后再试");
        }
    }

注:MyConfig仅个人配置,若有需要请访问榛子云官方网站

步骤4:后端校验

    /**
     * 验证码登录
     */
    @RequestMapping("loginByCode")
    public R loginByCode(Auth user) {
        Object code = redisTemplate.opsForValue().get("key-" + user.getAuthPhone());// 通过手机号获取redis中验证码
        if (code == null) {
            // 如果验证码为null则提醒用户重新发送
            return R.failed("请重新发送验证码");
        }
        if (!StrUtil.equalsIgnoreCase(code.toString(), user.getAuthCode())) {
            // 如果验证码不为空但与redis存储的验证码不符则提示验证码错误
            return R.failed("验证码错误");
        }
        // 查询用户信息
        QueryWrapper<Auth> wrapper = new QueryWrapper<>();
        // 通过"手机号"查询用户
        wrapper.eq("auth_phone", user.getAuthPhone());
        // 获取查询到的用户信息
        Auth one = authService.getOne(wrapper);
        // 判断用户是否存在
        if (one == null) {
            // 通过雪花算法为用户"盐"赋值
            user.setSalt(IdUtil.getSnowflake().nextIdStr());
            // 等待用户设置密码
            user.setAuthPwd(null);
            // 添加用户信息到数据库
            authService.save(user);
            one = user;
        }
        // 加密签名
        byte[] key = one.getSalt().getBytes();
        // 通过用户id获取Token
        String token = JWT.create().setPayload("id", user.getAuthId()).setKey(key).sign();
        return R.successed(token);
    }

附带:榛子云配置解析

    /**
     * 榛子云配置
     */
    public static final String appId = "******";
    public static final String appSecret = "********-****-****-****-************";
    public static final String appUrl = "https://sms_developer.zhenzikj.com";
    public static final String templateIdOne = "*****";// 验证码
    public static final String templateIdTwo = "*****";// 新年祝福

文章来源:https://blog.csdn.net/Domain_2022/article/details/135537256
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。