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

分享好友

×
取消 复制
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-12-17 23:23:23
0
分享好友

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

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

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

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

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

栈主、嘉宾

查看更多
  • unnamed person1
    栈主

小栈成员

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