文件管理(demo)注册时的邮件验证

写在开头:本篇文章记录于22年4月23,一个暖洋洋的下午

实现功能

用户在注册时需要输入邮件并完成验证,方可进行完整注册。

逻辑实现

---->前端邮箱输入栏右侧加一个发送邮件按钮

--->点击按钮,携带邮箱向后端发起发送邮件的请求

--->后端接收请求,生成5位随机验证码,一方面将验证码作为邮件内容发送,另一方面将验证码写入redis并设置1分钟的有效期。

--->前端用户收到验证码,提交注册表单(包含验证码)

--->后端接收到注册表单,现拿表单里的邮箱去redis进行验证码效验,若reids已没有验证码,返回验证码已失效,用邮箱查到的验证码表单不一致,则返回验证码错误,若效验成功则进行后续的账号验证与数据库的写入

--->前端验证码失效,按钮就显示重新发送,成功则跳转至登录页面

技术栈

前端:vue2.X + vue-admin-template

后端:springboot+mybatis-plus+mysql+springSecurity+jwt+shiro

代码实现(碍于篇幅,只显示关键代码,建议去文末的gitee仓库地址拉取文件管理项目(前后端)的完整代码)

依赖引入:

         <!--邮件服务-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <!--thylemeaf模板引擎(用于邮件模板设置)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--java常用工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.13</version>
        </dependency>
       <!--邮件服务-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

springboot配置

 #redis配置
  redis:
    # 地址
    host: 127.0.0.1
    # 端口号
    port: 6379
    # 密码(默认为空)
    password:
    # 超时时间,单位毫秒
    timeout: 3000
    # 数据库编号
    database: 0
    # 配置lettuce
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 1
        # 连接池中的最大空闲连接
        max-idle: 6
        # 连接池最大连接数(使用负值表示没有限制,不要配置过大,否则可能会影响redis的性能)
        max-active: 10
        # 连接池最大阻塞等待时间(使用负值表示没有限制);单位毫秒
        max-wait: 1000
      #关闭超时时间;单位毫秒
      shutdown-timeout: 200
#发送验证邮件
  mail:
    protocol: smtp
    host: smtp.qq.com
    port: 465
    #自己邮箱和协议密码(非邮箱密码)
    username: *******
    password: *******
    default-encoding: utf-8
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
          ssl:
            enable: true
          socketFactory:
            port: 465
            class: javax.net.ssl.SSLSocketFactory

shiro配置

@Component
public class ShiroConfig {

    @Bean
    public RedisTemplate<String, Object> template(RedisConnectionFactory factory) {
        // 创建RedisTemplate<String, Object>对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 配置连接工厂
        template.setConnectionFactory(factory);
        // 定义Jackson2JsonRedisSerializer序列化对象
        Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会报异常
        om.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.WRAPPER_ARRAY);
        jacksonSeial.setObjectMapper(om);
        StringRedisSerializer stringSerial = new StringRedisSerializer();
        // redis key 序列化方式使用stringSerial
        template.setKeySerializer(stringSerial);
        // redis value 序列化方式使用jackson
        template.setValueSerializer(jacksonSeial);
        // redis hash key 序列化方式使用stringSerial
        template.setHashKeySerializer(stringSerial);
        // redis hash value 序列化方式使用jackson
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();
        return template;
    }
}

发送邮件的service类

@Service
public class EmailService {
    @Value("${spring.mail.username}")
    private String sendEmailName;
    @Resource
    private JavaMailSender javaMailSender;
    @Resource
    private TemplateEngine templateEngine;
    @Resource
    private RedisTemplate<String, Object> redisTemplate ;

    //发送邮件
    public void sendEmail(String confirm,String email) {
        try {
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage);
            //设置邮件基本信息
            mimeMessageHelper.setSubject("欢迎来到李同学的文件管理系统:个人账号注册");
            mimeMessageHelper.setFrom(sendEmailName);
            mimeMessageHelper.setTo(email);
            mimeMessageHelper.setSentDate(new Date());
            //设置邮件内容模板
            Context context = new Context();
            context.setVariable("confirm", confirm);
            //使用thymeleaf的模板引擎
            String text = templateEngine.process("email.html", context);
            mimeMessageHelper.setText(text, true);
            //发送邮件
            javaMailSender.send(mimeMessage);
            //将验证码写入redis并设置1分钟有效期
            redisTemplate.opsForValue().set(email, confirm, 1, TimeUnit.MINUTES);
        } catch (Exception  e) {
            e.printStackTrace();
        }
    }

}

使用的thymeleaf邮件模板(将该eamil.html放入resources/templates/下)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:text="${confirm}"></title>
</head>
<body>
<p>这是由李同学的文件上传与下载系统发送的邮件:请不要泄露你的激活码</p>
</br>
<p th:text="你的激活码为 +${confirm}">你的激活码为:${}</p>
</body>
</html>

用户注册的service

//用户注册
    public Result register(VoUser voUser){
        User user=new User();
        if(voUser==null) return Result.fail("注册信息未填写完整");
        String salt= RandomUtil.randomString(5);
        String password = DigestUtil.md5Hex(voUser.getPassword()+salt);
        //效验账户
        QueryWrapper<User> query=new QueryWrapper<>();
        query.eq("username", voUser.getUsername())
                .or()
                .eq("email", voUser.getEmail())
                .or()
                .eq("phone_num", voUser.getPhoneNum());
        List<User> list = userService.list(query);
        if(!list.isEmpty()) return Result.fail("邮箱或用户名或手机号已被注册");
        //效验验证码,用前端传来的邮箱去redis中查询验证码
        String confirm=(String) redisTemplate.opsForValue().get(voUser.getEmail());
        if(confirm==null) return Result.fail("验证码已失效,请重新发送");
        else {
            if(!confirm.equals(voUser.getConfirm())) return Result.fail("验证码不正确");
        }
        //效验完毕,写入数据库
        user.setUsername(voUser.getUsername());
        user.setEmail(voUser.getEmail());
        user.setPhoneNum(voUser.getPhoneNum());
        user.setSalt(salt);
        user.setPassword(password);
        user.setRole("ROLE_admin");
        userService.save(user);
        return Result.succ("注册成功");
    }

注册和发送邮件的controller

    //发送邮件
    @GetMapping("/sendEmail")
    public Result sendEmail(String email){
        //生成五位随机验证码,注入邮件,同时返回给前端由于验证
        String confirm= RandomUtil.randomString(5);
        emailService.sendEmail(confirm,email);
        return Result.succ(confirm);
    }
    //注册用户
    @RequestMapping("/register")
    public Result register(@RequestBody VoUser voUser) {
        return loginService.register(voUser);
    }

效果展示

 写在最后

本文主要展示了涉及邮件验证的核心代码,与springSecurity, jwt, 文件上传下载的代码均在仓库里

项目的完整代码在:gitee仓库地址

有用的话给个star~~~~ 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值