目录

1.导入邮箱依赖2.有关application.yaml配置3.创建一个工具类生成验证码4.发送邮件验证码5.接收并使用邮件验证码6.效果展示7.思想总结

最近做一个社区项目,发现很多地方都需要校验是否为用户本人,然后做了个邮箱验证分享给大家,当然也可以采用手机验证码。思想和邮箱验证码是类似的,只需要稍作修改。废话不多说直接上代码。

1.导入邮箱依赖

我这里是基于spring boot下的maven项目,导入pom依赖。用的是springboot2.2.2版本。

org.springframework.boot

spring-boot-starter-mail

2.有关application.yaml配置

#邮件发送

spring:

mail:

username:XXXX@qq.com

#邮箱授权码,百度一下很简单

password: 授权码

host: smtp.qq.com

default-encoding: utf-8

#开启加密验证

properties:

mail:

smtp:

ssl:

enable: ture

3.创建一个工具类生成验证码

/**

* @Description TODO:邮箱验证码,采用SecureRandom真随机数

* @Author 郁郁201

* @Date 2020-01-20 17:03

* @Version 1.0

*/

public class VerCodeGenerateUtil {

//邮箱字符串提取,去除了容易混淆的几个字符比如0,o~

private static final String SYMBOLS = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";

private static final Random RANDOM = new SecureRandom();

/**

* 生成4位随机验证码

* @return 返回4位验证码

*/

public static String getVerCode() {

char[] nonceChars = new char[4];

for (int index = 0; index < nonceChars.length; ++index) {

nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));

}

return new String(nonceChars);

}

}

4.发送邮件验证码

创建ScheduledExecutorService线程池(该线程池,将计时和多线程结合一起,perfect),以便于多用户获取验证码放入session并计时。ReslutTypeDto为返回前端的数据类型,VisitorStatusEmun为枚举类型,存放多种结果操作,下面附有注释,可自行替换。

//创建线程池对象

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);

//这个是我用户Service实现类可以自行替换

@Autowired

UserServiceImpl userServiceImpl;

//这个是邮件类,必须要导入哦

@Autowired

JavaMailSenderImpl mailSender;

@GetMapping("/reg/sendEmail")

@ResponseBody

public ReslutTypeDto sendEmail(String email,HttpServletRequest request){

HttpSession session = request.getSession();

//验证码

String verCode = VerCodeGenerateUtil.getVerCode();

//发送时间 --这里自己写了一个时间类,格式转换,用于邮件发送

String time = DateUtils.date2String(new Date(), "yyyy-MM-dd hh:mm:ss");

Map map = new HashMap<>();

map.put("code",verCode);

map.put("email",email);

//验证码和邮箱,一起放入session中

session.setAttribute("verCode",map);

Map codeMap = (Map) session.getAttribute("verCode");

//创建计时线程池,到时间自动移除验证码

try {

scheduledExecutorService.schedule(new Thread(()->{

if(email.equals(codeMap.get("email"))){

session.removeAttribute("verCode");

}

}), 5*60, TimeUnit.SECONDS);

} catch (Exception e) {

e.printStackTrace();

}

//一下为发送邮件部分

MimeMessage mimeMessage = null;

MimeMessageHelper helper = null;

try {

//发送复杂的邮件

mimeMessage = mailSender.createMimeMessage();

//组装

helper= new MimeMessageHelper(mimeMessage, true);

//邮件标题

helper.setSubject("【Share社区】 注册账号验证码");

//因为设置了邮件格式所以html标签有点多,后面的ture为支持识别html标签

//想要不一样的邮件格式,百度搜索一个html编译器,自我定制。

helper.setText("

\n" +

"\t亲爱的用户: \n" +

"

\n" +

"

\n" +

"\t        您好!您正在进行邮箱验证,本次请求的验证码为: "+verCode+",本验证码5分钟内有效,请在5分钟内完成验证。(请勿泄露此验证码)如非本人操作,请忽略该邮件。(这是一封自动发送的邮件,请不要直接回复)\n" +

"

\n" +

"

\n" +

"\tShare社区 \n" +

"

\n" +

"

\n" +

"\t"+time+" \n" +

"

",true);

//收件人

helper.setTo(email);

//发送方

helper.setFrom(我的邮箱);

try {

//发送邮件

mailSender.send(mimeMessage);

} catch (MailException e) {

//邮箱是无效的,或者发送失败

return new ReslutTypeDto(VisitorStatusEmun.Email_Invalid);

}

} catch (MessagingException e) {

//发送失败--服务器繁忙

return new ReslutTypeDto(VisitorStatusEmun.Server_Busy);

}

//发送验证码成功

return new ReslutTypeDto(VisitorStatusEmun.Send_Email_Captcha_OK);

}

5.接收并使用邮件验证码

最后一步注册时使用验证码,获取了前端三个参数,邮箱(username),密码,验证码(vercode)。

//这里我采用的是email作为username

@PostMapping("/reg")

@ResponseBody

public ReslutTypeDto reg(String username,

String password,

String verCode,

HttpServletRequest httpServletRequest){

HttpSession session = httpServletRequest.getSession();

Map codeMap = (Map)session.getAttribute("verCode");

String code = null;

String email = null;

try {

code = codeMap.get("code");

email = codeMap.get("email");

} catch (Exception e) {

//验证码过期,或未找到 ---验证码无效

return new ReslutTypeDto(VisitorStatusEmun.Email_Captcha_Invalid);

}

//验证码判断

if (!verCode.toUpperCase().equals(code) || !username.equals(email)) {

return new ReslutTypeDto(VisitorStatusEmun.Email_Captcha_Fail);

}

//验证码使用完后session删除

session.removeAttribute("verCode");

User user = userServiceImpl.findUserByName(username);

//用户名是否可用

if (user!=null){

//返回,该用户)(username)已被注册过

return new ReslutTypeDto(VisitorStatusEmun.Account_Registered);

}

//数据库插入数据

Integer integer = userServiceImpl.addUser(username, password);

//是否插入数据成功

if (integer==null||!integer.equals(1)){

//返回注册失败

return new ReslutTypeDto(VisitorStatusEmun.Register_Fail);

}

//返回注册成功

return new ReslutTypeDto(VisitorStatusEmun.Register_OK);

}

6.效果展示

7.思想总结

验证码运用在项目中的还是挺简单的(需要全套源码评论区留邮箱哦),主要掌握核心思想,就是验证码的存放,移除。我这采用的session存放,当然大家也可已采用其他方式。以上就是发送邮箱验证码全过程了,如有纰漏还请多多指教~