目录

介绍

一、获取授权码

二、前端代码修改

三、后端代码修改

①pom依赖

②yml配置

③控制层

④业务层

⑤工具类


介绍

本文介绍了QQ邮箱验证码登录功能的实现步骤:

  1. 获取QQ邮箱授权码并配置;
  2. 前端修改登录页面,增加验证码发送接口调用和登录逻辑;
  3. 后端实现包括:添加邮件依赖、配置邮件参数、开发验证码发送接口(使用随机4位数字)、登录验证逻辑(自动注册新用户)、邮件发送服务等。

       重点使用了Spring Boot Mail组件实现邮件发送,通过Session存储验证码进行校验,并提供了完整的工具类生成随机验证码。系统实现了基于手机号和邮箱验证码的登录功能,包含自动注册新用户的能力。


一、获取授权码

QQ邮箱

生成授权码如下,最好截图保存,后续要用到


二、前端代码修改

2.1 调用发送验证码API接口,并取消自动填充验证码。代码位置:front/page/login.html

methods:{
  getCode(){
    this.form.code = ''
    const regex = /^(13[0-9]{9})|(15[0-9]{9})|(17[0-9]{9})|(18[0-9]{9})|(19[0-9]{9})$/;
    if (regex.test(this.form.phone)) {
      this.msgFlag = false
      // this.form.code = (Math.random()*1000000).toFixed(0)
      sendMsgApi({phone:this.form.phone})
    }else{
      this.msgFlag = true
    }
  },
  async btnLogin(){

    if(this.form.phone && this.form.code){
      this.loading = true
      // const res = await loginApi({phone:this.form.phone})
      const res = await loginApi({phone:this.form.phone,code:this.form.code})
      this.loading = false
      if(res.code === 1){
        sessionStorage.setItem("userPhone",this.form.phone)
        window.requestAnimationFrame(()=>{
          window.location.href= '/front/index.html'
        })                           
      }else{
        this.$notify({ type:'warning', message:res.msg});
      }
    }else{
      this.$notify({ type:'warning', message:'请输入手机号码'});
    }
  }

2.2 增加一个发送验证码API。代码位置:front/api/login.js

function loginApi(data) {
  return $axios({
    'url': '/employee/login',
    'method': 'post',
    data
  })
}

三、后端代码修改

①pom依赖

<!--mail短信依赖-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

②yml配置

这里需要配置【邮箱】和刚刚获取的【授权码】

spring:
  mail:
    host: smtp.qq.com
    #发送验证码的邮箱
    username: xxxxxxxxxxx@qq.com
    # 你的QQ邮箱授权码
    password: xxxxxxxxxxx
    ssl:
      enabled: true

③控制层

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Autowired
    private IUserService userService;
    //获取验证码
    @PostMapping("/sendMsg")
    public R<String> sendMsg(HttpSession session, @RequestBody User user){
        //获取邮箱号
        //相当于发送短信定义的String to
        String phone = user.getPhone();
        String subject = "瑞吉外卖";
        //StringUtils.isNotEmpty字符串非空判断
        if (StringUtils.isNotEmpty(phone)) {
            //发送一个四位数的验证码,把验证码变成String类型
            String code = ValidateCodeUtils.generateValidateCode(4).toString();
            String text = "【瑞吉外卖】您好,您的登录验证码为:" + code + ",请尽快登录";
            log.info("验证码为:" + code);
            //发送短信
            userService.sendMsg(subject,text);
            //将验证码保存到session当中
            session.setAttribute(phone,code);
            return R.success("验证码发送成功");
        }
        return R.error("验证码发送异常,请重新发送");
    }
    //登录
    @PostMapping("/login")
    //Map存JSON数据
    public R<User> login(HttpSession session,@RequestBody Map map){
        //获取邮箱,用户输入的
        String phone = map.get("phone").toString();
        //获取验证码,用户输入的
        String code = map.get("code").toString();
        //获取session中保存的验证码
        Object sessionCode = session.getAttribute(phone);
        //如果session的验证码和用户输入的验证码进行比对,&&同时
        if (sessionCode != null && sessionCode.equals(code)) {
            //要是User数据库没有这个邮箱则自动注册,先看看输入的邮箱是否存在数据库
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getPhone,phone);
            //获得唯一的用户,因为手机号是唯一的
            User user = userService.getOne(queryWrapper);
            //要是User数据库没有这个邮箱则自动注册
            if (user == null) {
                user = new User();
                user.setPhone(phone);
                user.setStatus(1);
                //取邮箱的前五位为用户名
                user.setName(phone.substring(0,6));
                userService.save(user);
            }
            //不保存这个用户名就登不上去,因为过滤器需要得到这个user才能放行,程序才知道你登录了
            session.setAttribute("user", user.getId());
            return R.success(user);
        }
        return R.error("登录失败");
    }
}

④业务层

接口

public interface IUserService extends IService<User> {
    void sendMsg(String subject,String text);
}

实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements IUserService {
    //把yml配置的邮箱号赋值到from
    @Value("${spring.mail.username}")
    private String email;
    //发送邮件需要的对象
    @Autowired
    private JavaMailSender javaMailSender;
    //邮件发送人
    @Override
    public void sendMsg(String subject, String text) {
        //发送简单邮件,简单邮件不包括附件等别的
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(email);
        message.setTo(email);
        message.setSubject(subject);
        message.setText(text);
        //发送邮件
        javaMailSender.send(message);
    }
}

⑤工具类

ValidateCodeUtils.java,黑马给了此代码;不用 SMSUtils.java

package com.itheima.reggie.utils;

import java.util.Random;

/**
 * 随机生成验证码工具类
 */
public class ValidateCodeUtils {
    /**
     * 随机生成验证码
     * @param length 长度为4位或者6位
     * @return
     */
    public static Integer generateValidateCode(int length){
        Integer code =null;
        if(length == 4){
            code = new Random().nextInt(9999);//生成随机数,最大为9999
            if(code < 1000){
                code = code + 1000;//保证随机数为4位数字
            }
        }else if(length == 6){
            code = new Random().nextInt(999999);//生成随机数,最大为999999
            if(code < 100000){
                code = code + 100000;//保证随机数为6位数字
            }
        }else{
            throw new RuntimeException("只能生成4位或6位数字验证码");
        }
        return code;
    }

    /**
     * 随机生成指定长度字符串验证码
     * @param length 长度
     * @return
     */
    public static String generateValidateCode4String(int length){
        Random rdm = new Random();
        String hash1 = Integer.toHexString(rdm.nextInt());
        String capstr = hash1.substring(0, length);
        return capstr;
    }
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐