SpringBoot使用邮箱发送验证码实现注册功能

作者:ForLevin 时间:2022-03-30 10:13:36 

本文为大家分享了SpringBoot使用邮箱发送验证码实现注册功能实例,供大家参考,具体内容如下

这里有两种方式:
使用Apache Common包中开源的email组件,通过实例化HtmlEmail()对象,可通过配置外置字典、或yml等配置文件实现灵活配置;

依赖:


<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-email</artifactId>
 <version>1.5</version>
</dependency>

使用SpringBoot Starter email组件;

依赖:


<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

我这里是采用的第一种方式,简单易懂;

首先需要配置Email的各项参数,其中hostname、host、username、passsword(注意:此处的密码并不是登录的密码,而是邮箱开启smtp服务的令牌);
我这里使用SpringBoot的yml配置文件,可以通过切换不同的环境:local/dev/test/pro/prod等等环境实现灵活配置,该配置为自定义配置;

我此处使用的是本人的163邮箱,在实际开发中需要换为公司的或项目专用邮箱;
(注意:此种方式有缺陷,即为不能从外部进行灵活配置,只能写死配置文件,在实际使用上应该配置为数据字典,可以在外部直接进行灵活配置)

yml:


##Email配置
email:
host-name: smtp.163.com #服务地址,可以直接在web端登录,找到smtp服务看到,163邮箱默认开放25端口,可暂时不设置
authentication:
 username: xxx.163.com
 password: xxx #手动的设置令牌
form:
 mail: xxx@163.com #发送方,必须为你设置的username一致
 name: elog #发送方显示的名称,可以随意设置
charset: UTF-8 #编码格式,一般设置为UTF-8

util:


package com.hisw.rest.utils;

import com.hisw.common.exception.RRException;
import org.apache.commons.mail.HtmlEmail;
/**
* @ClassName EmailCodeUtils
* @Description TODO 邮箱验证码工具类
* @Author liwenju
* @Date 2019/5/15 14:20
* @Version 1.0
**/
public class EmailCodeUtils {

/**
  * 生成6位随机验证码
  * @return
  */
 public static String getNumber(){
   String str = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   String code = "";
   for(int i= 0;i<6;i++){
     int index = (int)(Math.random()*str.length());
     code+=str.charAt(index);
   }
   return code;
 }

/**
  * 发送邮箱验证码
  * @param receiverEmail
  * @param subject
  * @param msg
  */
 public static void sendEmailCode(String EMAIL_HOST_NAME,String EMAIL_FORM_MAIL,
              String EMAIL_FORM_NAME,String EMAIL_AUTHENTICATION_USERNAME,
              String EMAIL_AUTHENTICATION_PASSWORD,String receiverEmail,
              String subject,String msg){
   try{
     HtmlEmail email = new HtmlEmail();
     email.setHostName(EMAIL_HOST_NAME);
     email.setCharset("utf-8");
     email.setFrom(EMAIL_FORM_MAIL,EMAIL_FORM_NAME);
     email.setAuthentication(EMAIL_AUTHENTICATION_USERNAME,EMAIL_AUTHENTICATION_PASSWORD);
     email.addTo(receiverEmail);
     email.setSubject(subject);
     email.setMsg(msg);
     email.send();
   }catch (Exception ex){
     throw new Exception("发送验证码失败,原因:"+ex.getMessage());
   }
 }

}

注意:在静态工具类的方法中,不可直接调用@Value(value="$xxx")来获取yml的配置文件的参数值,否则会获取不到值。故不在该util类中直获取。如下所示:


/**
* 获取邮箱配置
*/
@Value(value = "${email.host-name}")
public String EMAIL_HOST_NAME;

方法示例:


/**
* 获取邮箱配置
*/
@Value(value = "${email.host-name}")
public String EMAIL_HOST_NAME;

@Value(value = "${email.authentication.username}")
public String EMAIL_AUTHENTICATION_USERNAME;

@Value(value = "${email.authentication.password}")
public String EMAIL_AUTHENTICATION_PASSWORD;

@Value(value = "${email.charset}")
public String EMAIL_CHARSET;

@Value(value = "${email.form.mail}")
public String EMAIL_FORM_MAIL;

@Value(value = "${email.form.name}")
public String EMAIL_FORM_NAME;

@Autowired
private SysUserDao sysUserDao;

@Autowired
private SysUserTokenDao sysUserTokenDao;

@Autowired
private RedisUtils redisUtils;

private Logger logger = LoggerFactory.getLogger(LoginUserServiceImpl.class);
/**
* 验证码过期时间60s
*/
private Integer redisExpire = 60 * 1000;

/***
* 根据邮箱验证用户
* @param account
* @return
*/
public SysUserEntity queryByEmail(String account){
 SysUserEntity sysUserEntity = new SysUserEntity();
 sysUserEntity.setEmail(account);
 return sysUserDao.selectOne(sysUserEntity);
}

/**
* 判断该邮箱是否已存在
* @param email
* @return
*/
public Boolean checkEmail(String email){
 //首先判断该用户是否已存在
 if (StringUtils.isNotEmpty(email)){
   EntityWrapper<SysUserEntity> userEntityWrapper = new EntityWrapper<>();
   userEntityWrapper.eq("email",email);
   List<SysUserEntity> sysUserList = sysUserDao.selectList(userEntityWrapper);
   //如果已存在该用户
   return sysUserList.size() <= 0;
 }
 return true;
}

/**
*发送邮箱验证码
*
*/
public R sendRegisterEmailCode(String email) {
 try {
   //验证邮箱规则
   if (!RegexUtils.checkEmail(email)){
     throw new RRException("The mailbox does not conform to the specification!");
   }
   if (!checkEmail(email)){
     throw new RRException("This mailbox already exists. Please change the user's email and try again!");
   }
   String emailCode = EmailCodeUtils.getNumber();
   //发送验证码
   EmailCodeUtils.sendEmailCode(EMAIL_HOST_NAME, EMAIL_FORM_MAIL,
       EMAIL_FORM_NAME, EMAIL_AUTHENTICATION_USERNAME,
       EMAIL_AUTHENTICATION_PASSWORD, email, EmailTextTemplate.REGISTER_SUBJECT,
       EmailTextTemplate.REGISTER_CONTENT + emailCode + EmailTextTemplate.CONTENT_SUFFIX);
   logger.info("验证码发送成功:{}", email);
   //发送成功,将该验证码按照规定格式放入redis
   redisUtils.set(RestRedisConstant.REST_ELOG_REGISTER_EMAIL_CODE_KEY + email, emailCode, redisExpire);
   logger.info("Redis存储验证码成功:{}", emailCode);
   return R.ok("The verification code has been sent to your mailbox and is valid for 60 seconds.");
 } catch (Exception ex) {
   return R.error(ex.getMessage());
 }
}

/**
*验证验证码
/
public R checkRegisterEmailCode(String email, String code) {
 try {
   String redisCode = redisUtils.get(RestRedisConstant.REST_ELOG_REGISTER_EMAIL_CODE_KEY+email);
   //判断是否已过期
   if (StringUtils.isEmpty(redisCode)){
     return R.error("The E-mail verification code has expired, please try again.");
   }
   //判断验证码是否正确
   if (!StringUtils.equals(redisCode,code)){
     return R.error("The E-mail verification code is wrong. Please try again.");
   }
   //验证成功,从redis中移除该key&value
   redisUtils.delete(RestRedisConstant.REST_ELOG_REGISTER_EMAIL_CODE_KEY+email);
   return R.ok("The E-mail verification code has been verified.");
 }catch (Exception ex){
   throw new RRException(ex.getMessage());
 }
}

说明:R.error (msg)/ throw new RRExcepion(msg)中,msg应该以enum或常量的方式组织起来;
在发送验证码、校验验证码时,应该有一个工具类,验证一个邮箱在特定的短时间内只能发送或验证几次验证码,超过此限制,应该拒绝处理请求;

来源:https://blog.csdn.net/ForLevin/article/details/90292380

标签:SpringBoot,邮箱,注册
0
投稿

猜你喜欢

  • SpringBoot集成gRPC微服务工程搭建实践的方法

    2022-03-11 22:10:39
  • C#开发WinForm之DataGridView开发详解

    2023-06-25 06:31:35
  • Entity Framework模型优先与实体对象查询

    2022-11-18 07:19:36
  • java求数组元素重复次数和java字符串比较大小示例

    2023-08-04 22:20:02
  • mongo分布式锁Java实现方法(推荐)

    2023-06-30 21:28:43
  • Struts2学习手册之文件上传基础教程

    2021-10-11 19:27:07
  • java实现的日期时间转换工具类完整示例

    2022-10-08 19:05:28
  • 基于Unity制作一个简易的计算器

    2023-02-18 10:02:39
  • Java Base64算法实际应用之邮件发送实例分析

    2022-08-08 04:00:04
  • spring boot devtools在Idea中实现热部署方法

    2023-07-20 02:31:25
  • java写卷积神经网络(CupCnn简介)

    2022-12-11 09:33:09
  • 详解Spring Cloud Eureka多网卡配置总结

    2023-11-09 07:33:15
  • C#基础之数组排序、对象大小比较实现代码

    2023-05-05 12:36:50
  • JavaEE微框架Spring Boot深入解读

    2021-07-31 14:24:55
  • c# WPF中的TreeView使用详解

    2021-05-24 15:17:58
  • Android编程简单实现九宫格示例

    2021-12-06 21:43:57
  • 浅谈MyBatis中@MapKey的妙用

    2023-09-25 10:42:02
  • Android Studio 新建项目通过git上传到码云图文教程详解

    2021-08-09 12:12:05
  • Java实现考试系统

    2023-11-18 04:15:03
  • Java多线程回调方法实例解析

    2023-11-04 01:40:01
  • asp之家 软件编程 m.aspxhome.com