邮箱验证激活账号

1. 流程

  • 我们注册账号的时候会收到一封邮件,点击邮件里的链接就激活账号,这个功能很常见。其实就是在用户表里面加statecode字段,state表示激活状态,code是激活码
  • 用户填写账号点击注册,接着后台就往数据库插入数据,数据中state字段为0(表示未激活),还有个随机的code
  • 之后就向该用户发送邮件,邮件里有一个激活账号的URL(URL有用户id和对应的随机激活码)
  • 用户点击邮件的链接,就会带上用户id和激活码来到激活页面激活账号,若邮件的参数和数据库参数一致则激活账号,更新字段state未为1,否则不激活
  • 这里只介绍最基本的功能,还有激活码的过期时间,激活不成功删除账号,密码加盐等细节没有实现,还有这里的项目没有前端页面,一切功能从地址栏实现,请各位酌情考虑

2. 环境与依赖

  • IDEA
  • Maven

依赖

<!--  父工程  -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>

<!--  JDK版本  -->
<properties>
<java.version>1.8</java.version>
</properties>

<!--  各种依赖  -->
<dependencies>


<!--  Web启动类  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- 阿里巴巴数据库连接池  -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>
<!-- 连接池的启动器 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

<!--  添加数据库启动器  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--  数据库驱动,因为springboot不知道我们使用什么数据库  -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.28</version>
</dependency>
<!--  mybatis依赖  -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<!--  mybatis启动器依赖  -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<!--  Junit依赖  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--  邮件依赖  -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

SpringBoot配置文件

# 数据库连接池,自带hikari
# hikari:
#   maximum-pool-size: 30   # 最大连接数
#   minimum-idle: 10        # 最小连接数


# 自己的邮件配置
Howl:
  mail:
    from: XXXXXXXXXX@qq.com
    subject: 激活邮件
    address: http://localhost:8080


spring:
  # 数据源
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
    username: root
    password:
      druid:
        initial-size: 10
        min-idle: 5
        max-active: 20
        pool-prepared-statements: true

  # 邮件配置
  mail:
    host: smtp.qq.com
    port: 465
    username: XXXXXXXXXX@qq.com
    password: XXXXXXXXXXXXXXXXXX  #这里是smtp的密码,不是QQ密码
    protocol: smtp
    default-encoding: utf-8
    properties:
      mail:
        imap:
          ssl:
            socketFactory:
              fallback: false
        smtp:
          auth: true
          ssl:
            enable: true
            socketFactory:
              class: com.fintech.modules.base.util.mail.MailSSLSocketFactory
          starttls:
            enable: true
            required: true
      test-connection: false


# mybatis配置
mybatis:
  # 别名
  type-aliases-package: com.howl.dto
  # 映射文件路径,一般不用了
  # mapper-locations: classpath:mappers/*.xml
  configuration:
    # 开启驼峰映射
    map-underscore-to-camel-case: true

2. 项目结构

3. 数据库

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `state` int(1) NOT NULL DEFAULT '0' COMMENT '用户激活状态:0表示未激活,1表示激活',
  `code` varchar(255) NOT NULL COMMENT '激活码',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

4. DTO层

public class User {

    private int id;
    private String username;
    private String password;
    private String email;
    private String state;
    private String code;

    //Getters、Setters
    //Constructor
}

5. DAO层

  • 使用mybatis动态代理,编写的是接口
@Mapper
public interface UserMapper {

    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("INSERT INTO user (`username`,`password`,`email`,`code`) VALUES (#{username},#{password},#{email},#{code})")
    public int register(User user);

    @Select("SELECT * FROM user WHERE id = #{id}")
    public User getUserById(int id);

    @Update("UPDATE user SET state = 1 WHERE id = #{id} AND code = #{code}")
    public int updateByIdAndCode(int id, String code);
}

6. 工具类

邮件工具类

@Component
public class EmailUtil {

    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${Howl.mail.from}")
    private String from;
    @Value("${Howl.mail.subject}")
    private String subject;
    @Value("${Howl.mail.address}")
    private String address;

    public void sendEmail(int id, String code, String to) {

        String url = address + "/verify?id=" + id + "&code=" + code;
        String label = "<a href=" + url + ">点击此处激活账号,有没有反应可以复制链接从浏览器打开</a>";

        try {
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
            messageHelper.setFrom(from);
            messageHelper.setTo(to);
            messageHelper.setSubject(subject);
            messageHelper.setText(label,true);
            messageHelper.setSentDate(new Date());
            javaMailSender.send(mimeMessage);
        }catch (Exception e){
            new RuntimeException("邮件发送失败",e);
        }
    }
}

激活码

@Component
public class CodeUtil {

    public String getCode() {

        //返回UUID
        return UUID.randomUUID().toString().replace("-", "");
    }
}

7. Service层

@Service
public class UserService {

    @Autowired
    UserMapper userMapper;
    @Autowired
    EmailUtil emailUtil;
    @Autowired
    CodeUtil codeUtil;

    public int register(String username, String password, String email) {

        int result;
        String code = codeUtil.getCode();
        User user = new User(username, password, email, code);
        result = userMapper.register(user);

        // 开线程来发邮件,提高效率,发邮件很慢
        new Thread(() -> {
            emailUtil.sendEmail(user.getId(), code, email);
        }).run();
        return result;
    }

    public int verify(int id, String code) {

        User user = userMapper.getUserById(id);
        if (user != null) {
            return userMapper.updateByIdAndCode(id, code);
        }
        return 0;
    }
}

8. Controller层

@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping(value = "/register")
    public String register(String username, String password, String email) {
        return userService.register(username, password, email) + "";
    }

    @GetMapping(value = "/verify")
    public String verify(int id, String code) {
        return userService.verify(id, code) + "";
    }
}

9. SpringBoot入口

@SpringBootApplication
@MapperScan("com.howl.dao")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

10. 测试

都看到这里了,没有前端页面。。。大家自行想象登录操作

10.1 注册

这里使用地址栏GET方式注册,正式注册用POST表单的不要学我,为了懒不想写前端

10.2 数据库插入

10.3 收邮件

10.4 点击链接激活

10.5 查看数据库激活状态

总结

实现太简单,不过基本功能还是有的,细节方面可以慢慢补充

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 初探Linux

    内核(Kernal):Linux最主要的部分,操作整个计算机的资源,提供内存管理,进程管理,驱动管理等基本功能

    晚上没宵夜
  • String

    String是最常操作的引用类型了,但也是我最怕的地方(因为不熟悉),最怕还是String和Array同时出现,所以现在先写下一篇博客熟悉熟悉字符串

    晚上没宵夜
  • 简单的权限(拦截)管理

    晚上没宵夜
  • MYSQL回顾(单表查询相关)

    ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and c...

    VV木公子
  • 使用Gradle的com.android.library插件构建aar的几个神坑

    使用apply plugin: 'com.android.library'方式,可以将so,res,classes.jar,AndroidManifest.xm...

    用户2930595
  • 剑指Offer面试题:26.字符串的排列

      我们可以把一个字符串看成由两部分组成:第一部分为它的第一个字符,第二部分是后面的所有字符。在下图中,我们用两种不同的背景颜色区分字符串的两部分。

    Edison Zhou
  • 快速学习-Skywalking的RPC调用-Dubbo的最佳实践

    接下来为大家提供一些简单使用Dubbo服务调用的项目代码演示, 大家可以参考下面简单版 或者详细请参照Demo中的脚手架示例scaffold-dubbo-de...

    cwl_java
  • SQN算法效果及代码: Breakout-ram-v4 打砖块

    再看LunarLander-v2的效果(也是比较简单了。。。),AverageEpRet就是不上300... : (

    用户1908973
  • PAT (Basic Level) Practice (中文)1057 数零壹

    给定一串长度不超过 105的字符串,本题要求你将其中所有英文字母的序号(字母 a-z 对应序号 1-26,不分大小写)相加,得到整数 N,然后再分析一下 N 的...

    C you again 的博客
  • PPT高仿《穹顶之下》曲线图

    曲线图的应用场景初中数学书里都写了,我就不多说了,这期我们通过《穹顶之下》里的一个关于减煤曲线的案例来探讨折线图的美化。

    卤代烃

扫码关注云+社区

领取腾讯云代金券