绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
5步Spring Boot搭建简易邮箱验证系统
2019-12-17 23:14:39

今天我们来看看如何用 Spring Boot 简易搭建一个邮箱验证接口。

许多的网站在注册账号之后,都会发送一封邮件到注册邮箱里,而用户需要到邮箱里打开这封验证邮件,并点击邮件里的链接,以向网站证明自己为该邮箱的拥有者。

1. 配置邮箱参数

为了让 Spring Boot 在用户注册成功的时候发送邮件,我们需要先添加一个邮箱服务依赖。

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-mail</artifactId>

</dependency>

1

2

3

4

我们需要配置一个邮箱服务来帮我们发送验证邮箱的邮件,但在配置邮箱参数之前,我们要先决定使用哪一个邮箱服务。这里我们以 QQ 邮箱为例子,朋友们也可以搭建自己的邮箱服务器。

登录 QQ 邮箱之后,点击 设置 -> 账户,打开 “POP3/SMTP服务”,接着取得第三方客户端授权码。

接着我们打开 application.properties 文件来进行配置:

spring.mail.host=smtp.qq.com

spring.mail.protocol=smtp

spring.mail.username= # 填写你的发件邮箱地址

spring.mail.password= # 填写第三方客户端授权码

spring.mail.default-encoding=UTF-8

spring.mail.port=465

# 此为邮件加密服务

spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

1

2

3

4

5

6

7

8

2. 创建实体类

当用户完成注册之后,我们需要在邮箱验证表里创建一条记录使用户的邮箱与一个的加密 token 匹配,以提升之后验证邮箱时的安全性。

用户需要点击带有该 token 参数的网址,接着我们会检查这个表,token 核对成功之后才算是成功验证邮箱。

创建一个邮箱验证表实体类:

@Entity

@Table(name = "email_verifier")

public class EmailVerifier {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private int id;

private String email;

private int userId;

// 验证用的 token

private String token;

// getters and setters

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

接着创建一个用户实体类。我们需要给用户实体类一个 boolean 值的属性,代表其邮箱是否已经通过验证。默认为 false,因为刚注册成功的时候邮箱肯定是还没有通过验证的。

@Entity

@Table(name = "users")

public class User {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private int id;

private String email;

// 邮箱是否成功验证,默认为 false

@Column(name = "is_email_verified", columnDefinition = "boolean default false")

private boolean isEmailVerified;

@JsonIgnore

private String password;

// getters and setters

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

3. 创建仓库类

我们需要写一个简单的用户仓库类

@Repository

@Transactional

public class UserRepositoryImpl implements UserRepository {

@PersistenceContext

private EntityManager entityManager;

// 将新用户插入用户表

public void addUser(String email, String password) {

User user = new User();

entityManager.persist(user);

user.setEmail(email);

user.setPassword(password);

entityManager.flush();

}

// 将用户表里的邮箱是否已验证属性设为 true

public void setUserEmailVerified(int userId) {

User user = findById(userId);

entityManager.persist(user);

user.setEmailVerified(true);

entityManager.flush();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

接着再写一个简单的邮箱仓库类

@Repository

@Transactional

public class EmailRepositoryImpl implements EmailRepository {

@PersistenceContext

private EntityManager entityManager;

// 往邮箱验证表添加新注册用户邮箱

public void addEmailVerifier(int userId, String email, String token) {

EmailVerifier emailVerifier = new EmailVerifier();

entityManager.persist(emailVerifier);

emailVerifier.setUserId(userId);

emailVerifier.setEmail(email);

emailVerifier.setToken(token);

entityManager.flush();

}

// 根据用户 id 取得邮箱验证表数据

public EmailVerifier getEmailVerifierByUserId(int userId) {

EmailVerifier emailVerifier = entityManager.createQuery("SELECT e FROM EmailVerifier e WHERE e.userId = :userId", EmailVerifier.class)

.setParameter("userId", userId)

.getSingleResult();

return emailVerifier;

}

// 根据 token 取得邮箱验证表数据

public EmailVerifier getEmailVerifierByToken(String token) {

EmailVerifier emailVerifier = entityManager.createQuery("SELECT e FROM EmailVerifier e WHERE e.token = :token", EmailVerifier.class)

.setParameter("token", token)

.getSingleResult();

return emailVerifier;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

4. 创建服务类

由于当我们向 QQ 邮箱发送请求时,整个线程需要等待 QQ 邮箱服务器返回发送结果,因此会导致线程堵塞,所以我们可以使用多线程来对 QQ 邮箱发送异步请求。

首先我们需要创建一个线程池配置类:

@EnableAsync // 使用该注解,这样 Spring Boot 才会扫描 @Async 注解

@Configuration

public class TaskPoolConfig {

@Bean("taskExecutor")

public Executor taskExecutor() {

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

executor.setCorePoolSize(4);

executor.setMaxPoolSize(8);

executor.setQueueCapacity(200);

executor.setKeepAliveSeconds(60);

executor.setThreadNamePrefix("task-executor");

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

executor.setWaitForTasksToCompleteOnShutdown(true);

executor.setAwaitTerminationSeconds(600);

return executor;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

接着在我们的邮箱业务逻辑中,我们会需要使用到 @Async 注解。

编写一个邮箱服务类

@Service

public class EmailServiceImpl implements EmailService {

@Autowired

private MailSender mailSender;

@Autowired

private EmailRepository emailRepository;

@Autowired

private UserRepository userRepository;

@Async("taskExecutor")

@Override

public void sendVerificationEmail(int userId) {

try {

SimpleMailMessage simpleMailMessage = new SimpleMailMessage();

EmailVerifier emailVerifier = getEmailVerifierByUserId(userId);

String email = emailVerifier.getEmail();

String token = emailVerifier.getToken();

String text = "请点击链接验证邮箱: https://此处输入你的主服务器地址/api/v1/user/email_verification?token=" + token;

simpleMailMessage.setTo(email);

simpleMailMessage.setSubject("Email Verification");

simpleMailMessage.setFrom("xxxx@qq.com"); // 填写你的 QQ 邮箱地址

simpleMailMessage.setText(text);

mailSender.send(simpleMailMessage);

} catch(Exception e) {

e.printStackTrace();

}

}

public void addEmailVerifier(int userId, String email, String token) {

emailRepository.addEmailVerifier(userId, email, token);

}

public EmailVerifier getEmailVerifierByUserId(int userId) {

return emailRepository.getEmailVerifierByUserId(userId);

}

public EmailVerifier getEmailVerifierByToken(String token) {

EmailVerifier emailVerifier = emailRepository.getEmailVerifierByToken(token);

return emailVerifier;

}

public void setUserEmailVerified(int userId) {

userRepository.setUserEmailVerified(userId);

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

这里我们使用 JWT 来作为我们的 token,因此我们需要添加 JWT 依赖

<dependency>

<groupId>com.auth0</groupId>

<artifactId>java-jwt</artifactId>

<version>3.4.0</version>

</dependency>

1

2

3

4

5

然后我们写一个用户的服务类

public class UserServiceImpl implements UserService {

@Autowired

private UserRepository userRepository;

@Autowired

private EmailService emailService;

// 这是生成 token 的密钥

private String tokenSecret = "my-secret-string";

// 添加新用户

public void addUser(String email, String password) {

User user = userRepository.addUser(email, password);

int userId = user.getId();

String token = token = JWT.create().sign(Algorithm.HMAC256(tokenSecret));

emailService.addEmailVerifier(userId, email, token);

emailService.sendVerificationEmail(userId);

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

5. 编写 REST 接口

我们还需要写 REST 接口来处理用户注册与验证邮箱的请求。

@CrossOrigin

@RestController

@RequestMapping(value = "/api/v1/user")

public class UserController {

@Autowired

private EmailService emailService;

@Autowired

private UserService userService;

// 用户注册 REST 接口

@PostMapping(value = "/signup")

public ResponseEntity<Object> signUp(@RequestBody Map<String, String> payload) {

JSONObject result = new JSONObject();

String email = payload.get("email");

String password = payload.get("password");

JSONObject addUserResult = userService.addUser(email, password);

return ResponseEntity.ok().build();

}

// 用户验证邮箱 REST 接口

@GetMapping(value = "/email_verification")

public ResponseEntity<Object> verifyEmail(HttpServletRequest request) {

String token = request.getParameter("token");

EmailVerifier emailVerifier = emailService.getEmailVerifierByToken(token);

if (emailVerifier != null) {

int userId = emailVerifier.getUserId();

emailService.setUserEmailVerified(userId);

return ResponseEntity.ok().body("邮箱验证成功");

} else {

return ResponseEntity.badRequest().build();

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

大功告成!让我们来测测实际效果。

实际效果

首先通过注册 REST API 注册一个账户。

可以使用 Postman 发送注册请求:

// 你的主机地址/api/v1/user/signup

{

"email": "填写你的邮箱",

"password": "123123"

}

1

2

3

4

5

接着就会收到一封邮箱验证邮件。

点击链接之后就会看到

接着我们到 Users 表查看用户的邮箱验证情况,已经从 false 变为 true了。

至此,一个简单的邮箱验证系统就搭建完了。

————————————————

版权声明:本文为CSDN博主「David Chou」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/vandavidchou/article/details/103514049

分享好友

分享这个小栈给你的朋友们,一起进步吧。

网络、数据安全
创建时间:2019-11-27 14:29:45
密码算法对数据进行主动保护,信息存储手段对数据进行主动防护
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • unnamed person1
    栈主

小栈成员

查看更多
  • pswyjz
  • 得一技术
  • xiaojun63
  • ?
戳我,来吐槽~