基于SpringBoot实现邮箱验证码注册

目录

一、简介

二、代码实现

1. 添加pom依赖

2. 创建邮件发送信息传输类、授权信息类

3. 创建邮箱服务接口和实现类

4. 修改配置文件application.yml,添加相关配置信息

5. 创建邮件模板

6. 创建功能服务接口与实现类

7. 编写Controller层API接口

三、结果演示

1. 发送邮箱验证码接口

2. 注册账号接口

3. 验证码邮件示例​编辑


一、简介

        用户注册系统时,一般会以邮箱进行关联注册,需要用户输入邮箱地址以获取随机验证码,然后在注册页面输入该验证码并完善其他相关注册信息点击注册,完成注册。

        基于SpringBoot的后端开发项目实现的逻辑分为两步:

  1. 向邮箱发送随机验证码;
  2. 收到用户输入验证码进行校验完成注册;

二、代码实现

1. 添加pom依赖

    <!-- spring data redis 依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- hutool工具包依赖-->
    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.5.7</version>
    </dependency>
    <!--  mail依赖-->
    <dependency>
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>1.4.7</version>
    </dependency>
    <!--  模板引擎依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>

2. 创建邮件发送信息传输类、授权信息类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmailDto {

    /**
     * 发送邮箱列表
     */
    private List<String> tos;

    /**
     * 主题
     */
    private String subject;

    /**
     * 内容
     */
    private String content;

}
@ApiModel(value = "授权用户信息")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AuthUserDto {


    @ApiModelProperty(value = "用户名")
    private String username;

    @ApiModelProperty(value = "密码")
    private String password;

    @ApiModelProperty(value = "临时登录凭证")
    private String code;

    @ApiModelProperty(value = "邮箱")
    private String email ;

}

3. 创建邮箱服务接口和实现类

public interface EmailService {

    /**
     * 发送邮件
     *
     * @param emailDto 邮箱列表
     */
    void send(EmailDto emailDto);
}
@Service
@RequiredArgsConstructor
public class EmailServiceImpl implements EmailService {

    @Value("${spring.mail.email}")
    private String email;
    @Value("${spring.mail.host}")
    private String host;
    @Value("${spring.mail.port}")
    private String port;
    @Value("${spring.mail.username}")
    private String username;
    @Value("${spring.mail.password}")
    private String password;

    @Override
    public void send(EmailDto emailDto) {

        // 读取邮箱配置
        if (email == null || host == null || port == null || username == null || password == null) {
            throw new RuntimeException("邮箱配置异常");
        }

        // 设置
        MailAccount account = new MailAccount();
        account.setHost(host);
        account.setPort(Integer.parseInt(port));
        // 设置发送人邮箱
        account.setFrom(username + "<" + email + ">");
        // 设置发送人名称
        account.setUser(username);
        // 设置发送授权码
        account.setPass(password);
        account.setAuth(true);
        // ssl方式发送
        account.setSslEnable(true);
        // 使用安全连接
        account.setStarttlsEnable(true);

        // 发送邮件
        try {
            int size = emailDto.getTos().size();
            Mail.create(account)
                    .setTos(emailDto.getTos().toArray(new String[size]))
                    .setTitle(emailDto.getSubject())
                    .setContent(emailDto.getContent())
                    .setHtml(true)
                    //关闭session
                    .setUseGlobalSession(false)
                    .send();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

    }
}

4. 修改配置文件application.yml,添加相关配置信息

mail:
    # 负责发送验证码的邮箱
    email: XXXX@126.com
    host: smtp.126.com
    port: 465
    username: XXXX
    # 授权码是用于登录第三方邮件客户端的专用密码。
    password: XXXXXXXXX



#邮箱验证码有效时间/秒
code:
  expiration: 300

此处授权密码需要在邮箱中申请配置,如下获取一个授权密码:【登录邮箱】-【设置】,springboot即可通过邮箱+授权码自动发送验证码邮件:

5. 创建邮件模板

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <style>
        @page {
            margin: 0;
        }
    </style>
</head>
<body>
<div class="header">
    <div style="padding: 10px;padding-bottom: 0px;">
        <p style="margin-bottom: 10px;padding-bottom: 0px;">尊敬的用户,您好:</p>
        <p style="text-indent: 2em; margin-bottom: 10px;">您正在注册【XXX平台】账号,您的验证码为:</p>
        <p class="code-text">${code}</p>
        <div class="footer">
        </div>
    </div>
</div>
</body>
</html>

<style lang="css">
    body {
        margin: 0px;
        padding: 0px;
        font: 100% SimSun, Microsoft YaHei, Times New Roman, Verdana, Arial, Helvetica, sans-serif;
        color: #000;
    }

    .header {
        height: auto;
        width: 820px;
        min-width: 820px;
        margin: 0 auto;
        margin-top: 20px;
        border: 1px solid #eee;
    }

    .code-text {
        text-align: center;
        font-family: Times New Roman;
        font-size: 22px;
        color: #C60024;
        padding: 20px 0px;
        margin-bottom: 10px;
        font-weight: bold;
        background: #ebebeb;
    }

    .footer {
        margin: 0 auto;
        z-index: 111;
        width: 800px;
        margin-top: 30px;
        border-top: 1px solid #DA251D;
    }
</style>

6. 创建功能服务接口与实现类

public interface AuthService {

    /**
     * 向指定邮箱发送验证码
     *
     * @param email 邮箱号
     * @return 结果
     */
    RespBean sendMailCode(String email);

    /**
     * 注册
     *
     * @param authUserDto 认证用户请求信息
     * @return 是否成功
     */
    RespBean register(AuthUserDto authUserDto);
}

 主要实现两个功能

  1. 向邮箱发送随机验证码;sendMailCode
  2. 收到用户输入验证码进行校验完成注册;register
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class AuthServiceImpl implements AuthService {

    @Value("${code.expiration}")
    private Long expiration;

//    private final IAdminService adminService;
//    private final RedisUtils redisUtils;
    private final EmailService emailService;
    private final PasswordEncoder passwordEncoder;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private AdminServiceImpl adminService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RespBean register(AuthUserDto authUserDto) {
        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
        // 通过email获取redis中的code
        Object value = valueOperations.get(authUserDto.getEmail());
        if (value == null || !value.toString().equals(authUserDto.getCode())) {
            return RespBean.error("无效验证码!");
        }

        // 如果前端没有传入用户名,则以邮箱号作为用户名进行注册
        String userName = StringUtils.isEmpty(authUserDto.getUsername()) ? authUserDto.getEmail() : authUserDto.getUsername();

        if (adminService.getAdminByUserName(userName) != null) {
            return RespBean.error("用户名已存在!");
        }

        // 创建用户
        Admin admin = new Admin();
        admin.setUsername(userName);
        try {
            admin.setPassword(passwordEncoder.encode(authUserDto.getPassword()));
        } catch (Exception e) {
            return RespBean.error("注册密码异常!");
        }
        admin.setEmail(authUserDto.getEmail());
        if(adminService.create(admin) == null){
            return RespBean.error("用户注册失败!");
        };
        redisTemplate.delete(authUserDto.getEmail());
        return RespBean.success("用户注册成功!");
    }



    @Override
    public RespBean sendMailCode(String email) {

        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();

        // 查看注册邮箱是否存在
        if (adminService.registerEmailExist(email)) {
            return RespBean.error("邮箱已被注册!");
        }

        // 获取发送邮箱验证码的HTML模板
        TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("templates", TemplateConfig.ResourceMode.CLASSPATH));
        Template template = engine.getTemplate("email-code.ftl");

        // 从redis缓存中尝试获取验证码
        Object code = valueOperations.get(email);
        if (code == null) {
            // 如果在缓存中未获取到验证码,则产生6位随机数,放入缓存中
            code = RandomUtil.randomNumbers(6);
            try {
                valueOperations.set(email, code, expiration, TimeUnit.SECONDS);
            } catch (Exception e) {
                return RespBean.error("后台缓存服务异常");
            }
        }
        // 发送验证码
        emailService.send(new EmailDto(Collections.singletonList(email),
                "邮箱验证码", template.render(Dict.create().set("code", code))));
        return RespBean.success("验证码发送成功");

    }
}

7. 编写Controller层API接口

@Api(tags = "admin-controller")
@RestController
@RequestMapping("/user")
public class AdminController {

    @Autowired
    AuthServiceImpl authService;

    @ApiOperation(value = "发送邮箱验证码")
    @PostMapping("/getemailcode")
    public RespBean getEmailCode(@RequestParam String email) {
        return authService.sendMailCode(email);
    }

    @ApiOperation(value = "注册")
    @PostMapping("/register")
    public RespBean register(@RequestBody AuthUserDto authUserDto) {
        return authService.register(authUserDto);
    }

}

根据原项目完善用户服务类(adminService)相关的方法实现,即可实现邮箱验证码注册功能。

三、结果演示

1. 发送邮箱验证码接口

  • 请求方式:post

  • 请求地址:/user/getemailcode

  • 参数:

    { 
        "email": "XXXX@foxmail.com"
    }

2. 注册账号接口

  • 请求方式:post

  • 请求地址:/user/register

  • 参数:

    {
    	 "code": "214941",
    	 "email": "XXXXXXX@foxmail.com",
    	 "password": "123",
    	 "username": "myself"
    }

3. 验证码邮件示例

 参考:手把手教你通过SpringBoot实现邮箱注册码验证_智慧zhuhuix的博客-CSDN博客_springboot实现邮箱注册icon-default.png?t=M4ADhttps://blog.csdn.net/jpgzhu/article/details/119533833

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值