Java 集成阿里大鱼平台短信服务发送验证码 --- 补齐注册部分

下一篇:使用 Redis 用户登录,整合JWT

依旧是之前的分析图

1、后端

  • 注册前需要再次进行服务端校验
    • 用户名是否已被注册
    • 手机号是否已被注册
    • 验证码是否错误
    • 验证码是否实现
  • 密码使用 BCrypt 进行加密

Controller层

关于根据用户名校验和手机号校验的方法这里没有贴上去,简单的查询判断

package com.czxy.controller;

import com.czxy.pojo.User;
import com.czxy.service.UserService;
import com.czxy.vo.BaseResult;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author 庭前云落
 * @Date 2020/3/20 21:52
 * @description
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostMapping("/register")
    public BaseResult register(@RequestBody User user) {
        //服务端校验
        User result = userService.findByUsername(user.getUsername());
        if (result != null) {
            return BaseResult.error("用户名已经存在");
        }

        result = userService.findByMobile(user.getMobile());
        if (result != null) {
            return BaseResult.error("该手机号已被注册");
        }

        //验证码
        String code = stringRedisTemplate.opsForValue().get("sms_register" + user.getMobile());

        if (code == null) {
            return BaseResult.error("验证码无效");
        }
        if (!code.equalsIgnoreCase(user.getCode())) {
            return BaseResult.error("验证码不正确");
        }
        //注册
        userService.register(user);
        // 注册完成后删除redis中的验证码
        stringRedisTemplate.delete("sms_register" + user.getMobile());
        return BaseResult.ok("注册成功");
    }
}



注意一下:注册完成后删除 redis 中的验证码,一定放在判断语句后,不然验证码如果无意输错,点击了注册按钮,没经过判断 redis 里面就直接删了,之后再输入正确的,就算没到5分钟的失效时间也会 return "验证码失效"。日常滚雷

UserServiceImpl

使用BCrypt 密码加密

package com.czxy.service.Impl;

import com.czxy.mapper.UserMapper;
import com.czxy.pojo.User;
import com.czxy.service.UserService;
import com.czxy.utils.BCrypt;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @author 庭前云落
 * @Date 2020/3/20 21:47
 * @description
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    /**
     * 用户注册
     */
    public void register(User user){
        //密码加密
        String password = BCrypt.hashpw(user.getPassword());
        user.setPassword(password);

        //注册时间
        user.setCreatedAt(new Date());
        user.setUpdatedAt(user.getCreatedAt());

        //注册(添加)
        userMapper.insert(user);
    }
}

2、前端

前端使用的是 Nuxt.js ,如果想要入门学习,点击前往 Nuxt.js学习(一) --- 让你清晰了解Nuxt.js、Nuxt.js环境搭建,完整的一套,系统的全面学习。

前端就没什么,一些校验,调用后端接口,依旧是上代码

Register.vue

<template>
  <div>
    <TopNav></TopNav>
    <div style="clear:both;"></div>
    <HeaderLogo></HeaderLogo>
    <div style="clear:both;"></div>
    <!-- 正文 -->
    <!-- 注册内容start -->
    <div class="login w990 bc mt10 regist">
      <div class="login_hd">
        <h2>用户注册</h2>
        <b></b>
      </div>
      <div class="login_bd">
        <div class="login_form fl">
          <form action method="post">
            <ul>
              <li>
                <label for>用户名:</label>
                <input
                  type="text"
                  class="txt"
                  v-model="user.username"
                  name="username"
                  @blur="checkUsername"
                />
                <p>3-20位字符,可由中文、字母、数字和下划线组成</p>
                <p :class="userMsg.username.code==1?'success':'error'">{{userMsg.username.message}}</p>
              </li>
              <li>
                <label for>密码:</label>
                <input
                  type="password"
                  class="txt"
                  name="password"
                  v-model="user.p1"
                  @blur="checkpassword1"
                />
                <p>6-20位字符,可使用字母、数字和符号的组合,不建议使用纯数字、纯字母、纯符号</p>
                <p v-if="userMsg.password1.code==0" class="error">{{userMsg.password1.message}}</p>
              </li>
              <li>
                <label for>确认密码:</label>
                <input
                  type="password"
                  class="txt"
                  name="password"
                  v-model="user.p2"
                  @blur="checkpassword2"
                />
                <p>请再次输入密码</p>
                <p v-if="userMsg.password2.code==0" class="error">{{userMsg.password2.message}}</p>
              </li>
              <li>
                <label for>手机号码:</label>
                <input
                  type="text"
                  class="txt"
                  name="mobile"
                  v-model="user.mobile"
                  @blur="checkmobile"
                />
                <p>请输入手机号码</p>
                <p v-if="userMsg.mobile.code==1" class="success">{{userMsg.mobile.message}}</p>
                <p v-else class="error">{{userMsg.mobile.message}}</p>
              </li>
              <li class="checkcode">
                <label for>验证码:</label>
                <input type="text" name="checkcode" v-model="user.code" />
                <!-- prevent阻止事件冒泡行为 -->
                <button :disabled="btnDisabled" @click.prevent="sendSms">
                  发送验证码
                  <span v-show="btnDisabled">{{senconds}}秒</span>
                </button>
                <span :class="userMsg.smsData.code==1?'success':'error'">{{userMsg.smsData.message}}</span>
              </li>
              <li>
                <label for>&nbsp;</label>
                <input type="checkbox" class="chb" checked="checked" /> 我已阅读并同意《用户注册协议》
              </li>
              <li>
                <label for>&nbsp;</label>
                <input type="submit" value @click.prevent="register" class="login_btn" />
              </li>
            </ul>
          </form>
        </div>
        <div class="mobile fl">
          <h3>手机快速注册</h3>
          <p>
            中国大陆手机用户,编辑短信 “
            <strong>XX</strong>”发送到:
          </p>
          <p>
            <strong>1069099988</strong>
          </p>
        </div>
      </div>
    </div>
    <!-- 注册footer -->
    <div style="clear:both;"></div>
    <Footer></Footer>
  </div>
</template>

<script>
import TopNav from "../components/TopNav";
import HeaderLogo from "../components/HeaderLogo";
import Footer from "../components/Footer";
export default {
  head: {
    title: "注册页面",
    link: [{ rel: "stylesheet", href: "style/login.css" }],
    script: [
      { type: "text/javascript", src: "js/header.js" },
      { type: "text/javascript", src: "js/index.js" }
    ]
  },
  components: {
    TopNav,
    HeaderLogo,
    Footer
  },
  data() {
    return {
      user: {
        mobile: "",
        p1: "",
        p2: ""
      },
      userMsg: {
        //错误提示数据
        smsData: "",
        username: {},
        mobile: {},
        password1: {},
        password2: {}
      },
      btnDisabled: false, //倒计时控制变量
      senconds: 30, //默认倒计时数
      timer: null //接收定时器,清除定时器
    };
  },
  methods: {
    //校验用户名
    async checkUsername() {
      if (this.user.username == null) {
        this.userMsg.username = {
          code: 0,
          message: "用户名不能为空"
        };
        return;
      }
      let { data } = await this.$request.checkUsername(this.user.username);
      this.userMsg.username = data;
    },
    //校验手机号
    async checkmobile() {
      console.info(this.user);
      let { data } = await this.$request.checkmobile(this.user);
      this.userMsg.mobile = data;
    },
    //校验密码
    checkpassword1() {
      if (this.user.p1 == "") {
        this.userMsg.password1 = {
          code: 0,
          message: "密码不能为空"
        };
      }
    },
    //校验确认密码
    checkpassword2() {
      if (this.user.p2 == "") {
        this.userMsg.password2 = {
          code: 0,
          message: "确认密码不能为空"
        };
      } else if (this.user.p2 != this.user.p1) {
        this.userMsg.password2 = {
          code: 0,
          message: "两次输入密码不一致"
        };
      }
	  this.user.password = this.user.p2;
    },
    async sendSms() {
      //简单校验
      if (!this.user.username) {
        this.userMsg.username = {
          code: 0,
          message: "用户名不能为空"
        };
        return;
      }
      if (!this.user.mobile) {
        this.userMsg.mobile = {
          code: 0,
          message: "手机号不能为空"
        };
        return;
      }

      //倒计时
      //按钮状态变为不可用
      this.btnDisabled = true;
      this.timer = setInterval(() => {
        //小于1重置
        if (this.senconds <= 1) {
          //按钮回到可用状态
          this.btnDisabled = false;
          //关闭定时器
          clearInterval(this.timer);
        } else {
          this.senconds--;
        }
      }, 1000);

      //继续发送
      let { data } = await this.$request.sendSms(this.user);
      if (data.code == 1) {
        //发送成功
        alert(data.message);
      } else {
        //错误信息
        this.userMsg.code = data.message;
      }
    },
    async register() {
      let { data } = await this.$request.register(this.user);
      if (data.code == 1) {
        this.$router.push("/login");
      } else {
        this.userMsg.smsData = data;
      }
    }
  }
};
</script>

<style>
</style>

api.js

//自定义函数
const request = {
    //checkUsername
    checkUsername: (username) => {
        return axios.post('/cgwebservice/user/checkusername', { username })
    },
    //checkmobile
    checkmobile: (user) => {
        return axios.post('/cgwebservice/user/checkmobile', user)
    },
    //发验证码
    sendSms: (user) => {
        return axios.post('/cgwebservice/sms', user)
    },
    register: (user) => {
        return axios.post('/cgwebservice/user/register', user)
    }
}

var axios = null
export default ({ $axios }, inject) => {

    //3) 保存内置的axios
    axios = $axios

    //4) 将自定义函数交于nuxt
    // 使用方式1:在vue中,this.$request.xxx()
    // 使用方式2:在nuxt的asyncData中,content.app.$request.xxx()

    inject('request', request)
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值