目录
介绍
一、获取授权码
二、前端代码修改
三、后端代码修改
①pom依赖
②yml配置
③控制层
④业务层
⑤工具类
介绍
本文介绍了QQ邮箱验证码登录功能的实现步骤:
- 获取QQ邮箱授权码并配置;
- 前端修改登录页面,增加验证码发送接口调用和登录逻辑;
- 后端实现包括:添加邮件依赖、配置邮件参数、开发验证码发送接口(使用随机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})$/;// 修复后的正则表达式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 = falseif(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: xxxxxxxxxxxssl:enabled: true
③控制层
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {@Autowiredprivate IUserService userService;//获取验证码@PostMapping("/sendMsg")public R<String> sendMsg(HttpSession session, @RequestBody User user){//获取邮箱号//相当于发送短信定义的String toString 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;//发送邮件需要的对象@Autowiredprivate JavaMailSender javaMailSender;//邮件发送人@Overridepublic 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);//生成随机数,最大为9999if(code < 1000){code = code + 1000;//保证随机数为4位数字}}else if(length == 6){code = new Random().nextInt(999999);//生成随机数,最大为999999if(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;}
}