基本想法就是1、后端发送邮箱验证码。2、用户输入验证码,后端在进行验证码校验。
其他该有的邮件校验参数等方法就自行考虑清楚,本文主要记录两个主要功能如何实现。
package com.lcc.myblog.utils;
import jakarta.annotation.Resource;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import java.time.Duration;
@Component
public class MailUtil {
@Resource
private JavaMailSenderImpl mailSender;
@Autowired
private RedisTemplate<String,String> redisTemplate;
public boolean mail(String email) throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
//生成随机验证码
String code = CodeGeneratorUtil.generateCode(6);
System.out.println("用户:"+email+" 生成的验证码是:"+code);
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
//设置一个html邮件信息
helper.setText("短信验证码功能测试!,你的验证码为:"
+ code + "(有效期为一分钟)", true);
//设置邮件主题名
helper.setSubject("LCC----发来了验证码");
//发给谁-》邮箱地址
helper.setTo(email);
//谁发的-》发送人邮箱
helper.setFrom("你自己的qq邮箱");
redisTemplate.opsForValue().set(email, code, Duration.ofMinutes(1));
mailSender.send(mimeMessage);
return true;
}
}
package com.lcc.myblog.utils;
import java.util.UUID;
public class CodeGeneratorUtil {
/**
* 生成指定长度的验证码
*
* @param length 长度
* @return
*/
public static String generateCode(int length) {
return UUID.randomUUID().toString().substring(0, length);
}
/**
* 雪花算法生成用户注册
*/
public static long snowflake() {
SnowUtil idutil = new SnowUtil();
return idutil.nextId();
}
}
<!-- 邮箱验证码 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
mail:
# 发送者邮箱
username: ""
#申请到的授权码
password: ""
# 配置 SMTP 服务器地址
host: smtp.qq.com
# 端口号465或587
port: 465
protocol: smtps
# 默认的邮件编码为UTF-8
default-encoding: UTF-8
# 配置SSL 加密工厂
properties:
mail:
smtp:
socketFactoryClass: javax.net.ssl.SSLSocketFactory
#表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
debug: true
ssl: true
这里需要申请授权码,要去邮箱里去设置,流程如下:
创建一个EmailController,里面设置两个方法,一个是发送邮件,一个是验证。
注意这里需要redis缓存验证码过期时间,因为验证码属于一个经常变化的信息。
package com.lcc.myblog.controller;
import com.lcc.myblog.pojo.Result;
import com.lcc.myblog.utils.MailUtil;
import com.lcc.myblog.utils.ThreadLocalUtil;
import jakarta.mail.MessagingException;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@Validated
public class EmailController {
@Autowired
private MailUtil mailUtil;
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 发送验证码
@PostMapping("/emailCode")
public Result emailCode(@Email String email) throws MessagingException {
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
String code = stringStringValueOperations.get(email);
//若redis存在
if (!StringUtils.isEmpty(code)){
return Result.error(email+": +" + code + "已存在,还未过期");
}
if (mailUtil.mail(email)){
return Result.success();
}
return Result.error("邮箱发送失败");
}
//验证验证码
@PostMapping("/code")
public Result<String> SureCode(@Pattern(regexp ="^.\\S{5,6}" )String code,@Email String email ){
//打印
System.out.println("新邮箱: "+email+" ,用户填写的验证码是: "+code);
//从redis里拿出code
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
String OriCode = stringStringValueOperations.get(email);
System.out.println("新邮箱: "+email+" ,后端生成的验证码是: "+OriCode);
if (StringUtils.isEmpty(OriCode)){
return Result.error( "验证码已失效,请重新发送!");
}
if (code.equals(OriCode)){
System.out.println("比较正确");
System.out.println(Result.success(email));
return Result.success(email);
}
return Result.error("验证码不正确!");
}
}
<el-form :model="userInfo" :rules="rules" label-width="100px" size="large">
<el-form-item label="登录名称">
<el-input v-model="userInfo.username" disabled></el-input>
</el-form-item>
<el-form-item label="性别生日">
<el-col :span="8">
<el-select v-model="userInfo.sex" placeholder="请选择你的性别">
<el-option label="男" value="男" />
<el-option label="女" value="女" />
</el-select>
</el-col>
<el-col style="margin-left: 20px;" :span="12">
<el-date-picker label="生日" v-model="userInfo.birthday" type="date" placeholder="生日"
style="width: 100%" />
</el-col>
</el-form-item>
<el-form-item label="用户昵称" prop="nickname">
<el-span span="8">
<el-input v-model="userInfo.nickname"></el-input>
</el-span>
</el-form-item>
<el-form-item label="用户邮箱" prop="email">
<el-col span="12">
<el-input :disabled="flag" v-model="userInfo.email"></el-input>
</el-col>
<el-col style="margin-left: 25px;" span="12">
<el-link v-if="flag" type="primary" size="large" @click="clickemaliupdate">点击修改</el-link>
<el-link v-else type="danger" size="large" @click="cancleEmail">取消修改</el-link>
</el-col>
</el-form-item>
<el-form-item v-show="!flag" label="邮箱验证码" prop="code">
<el-input style="width: 150px; margin-right: 20px;" placeholder="邮箱验证码" v-model="userInfo.code"></el-input>
<el-button type="primary" v-if="flag2" @click="clickEmail">发送验证码</el-button>
<el-button type="success" v-else @click="clickSureCode" >确认验证码</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="updateUserInfo">保存修改</el-button>
</el-form-item>
</el-form>
import { userMailService } from '@/api/user.js'
// 2 发送邮箱验证码
const SendMail = async()=>{
if(originEmail.value === userInfo.value.email){
ElMessage.error("邮箱未更改,无需发送");
flag2.value=true
}else{
let resultMail =await userMailService(userInfo.value)
console.log("这个东西是"+resultMail.code)
if(resultMail.code===0){
ElMessage.success("发送成功")
flag2.value=false
}
if(resultMail.code===1){
ElMessage.error(resultMail.value.message)
}
}
}
// 1 点击发送邮件
const clickEmail = ()=>{
SendMail()
}
// 点击修改邮箱
const clickemaliupdate = ()=>{
flag.value = false
flag2.value=true
}
// 取消修改邮件
const cancleEmail=()=>{
flag.value = true
flag2.value=false
// 还原邮箱值
userInfo.value.email = originEmail.value
}
import { UserSureCodeService } from '@/api/user.js'
// 确认验证码
const clickSureCode=async()=>{
let reslut = await UserSureCodeService(userInfo.value)
console.log("异步后"+reslut.data)
if(reslut.code === 0){
ElMessage.success("邮箱验证成功")
originEmail.value=reslut.data
// 更改修改状态
cancleEmail()
}else{
ElMessage.error(reslut.value.message)
}
}
// 发送邮件,生成验证码
export const userMailService = (userInfo)=>{
let params = new URLSearchParams();
params.append('email',userInfo.email)
return request.post('/emailCode',params)
}
//验证验证码code
export const UserSureCodeService=(userInfo)=>{
let params = new URLSearchParams();
params.append('code',userInfo.code)
params.append('email',userInfo.email)
return request.post("/code",params)
}