Springboot实现邮箱验证码注册与修改密码及登录功能详解流程

在 pom.xml 文件中导入以下依赖:

Springboot实现邮箱验证码注册与修改密码及登录功能详解流程

1. 准备工作

1.1 导入依赖

pom.xml 文件中导入以下依赖:

<!-- Spring Boot -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Data JPA -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- JDBC驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<!-- 邮箱发送 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

<!-- Security -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- Thymeleaf -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- Validation -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

1.2 配置文件

application.yml 文件中配置数据库、邮箱、安全等相关信息。

2. 实现激活码注册功能

2.1 用户实体类设计

com.example.entity 包下创建 User 实体类:

@Entity
@Table(name = "t_user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @NotBlank(message = "用户名不能为空")
    private String username;

    @NotBlank(message = "密码不能为空")
    private String password;

    @Email(message = "邮箱格式不正确")
    private String email;

    @NotNull(message = "激活状态不能为空")
    private Boolean activated = false;

    // getter、setter 省略
}

2.2 用户注册页面设计

resources/templates 目录下创建 register.html 页面(使用 Thymeleaf 模板引擎):

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>注册</title>
</head>
<body>
    <h1>注册</h1>

    <form method="post" action="/register">
        <label for="email">邮箱:</label>
        <input type="email" name="email" id="email" required />
        <br/>

        <label for="username">用户名:</label>
        <input type="text" name="username" id="username" required />
        <br/>

        <label for="password">密码:</label>
        <input type="password" name="password" id="password" required />
        <br/>

        <input type="submit" value="注册" />
    </form>
</body>
</html>

2.3 注册控制器设计

com.example.controller 包下创建 UserController 控制器:

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private MailSenderService mailSenderService;

    @GetMapping("/register")
    public String register() {
        return "register";
    }

    @PostMapping("/register")
    public String register(@Valid User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "register";
        }

        // 判断邮箱是否已注册
        if (userService.findByEmail(user.getEmail()) != null) {
            bindingResult.rejectValue("email", null, "该邮箱已注册");
            return "register";
        }

        // 生成随机激活码
        String activationCode = RandomStringUtils.randomAlphabetic(10);

        // 保存用户到数据库
        user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
        user.setActivated(false);
        user = userService.save(user);

        // 发送邮件
        mailSenderService.sendActivationMail(user.getEmail(), activationCode);

        return "redirect:/activate?email=" + user.getEmail();
    }

    @GetMapping("/activate")
    public String activate(String email, String activationCode, Model model) {
        User user = userService.findByEmail(email);

        if (user == null) {
            model.addAttribute("errorMsg", "用户不存在");
        } else if (user.getActivated()) {
            model.addAttribute("errorMsg", "用户已激活");
        } else if (StringUtils.equals(activationCode, user.getActivationCode())) {
            user.setActivated(true);
            userService.save(user);
            model.addAttribute("successMsg", "激活成功");
        } else {
            model.addAttribute("errorMsg", "激活码不正确");
        }

        return "activate";
    }
}

2.4 邮件发送服务设计

com.example.service 包下创建 MailSenderService 邮件发送服务:

@Service
public class MailSenderService {
    @Autowired
    private JavaMailSender mailSender;

    public void sendActivationMail(String email, String activationCode) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("your@mail.com"); // 发件人邮箱
        message.setTo(email); // 收件人邮箱
        message.setSubject("激活账号"); // 邮件主题
        message.setText("请点击链接进行激活:http://localhost:8080/activate?email=" + email + "&activationCode=" + activationCode); // 邮件内容
        mailSender.send(message);
    }
}

3. 实现修改密码功能

3.1 修改密码页面设计

resources/templates 目录下创建 reset_password.html 页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>修改密码</title>
</head>
<body>
    <h1>修改密码</h1>

    <form method="post" action="/reset_password">
        <input type="hidden" name="token" value="[[$token]]" />

        <label for="password">新密码:</label>
        <input type="password" name="password" id="password" required />
        <br/>

        <input type="submit" value="修改密码" />
    </form>
</body>
</html>

3.2 修改密码控制器设计

com.example.controller 包下创建 PasswordResetController 控制器:

@Controller
public class PasswordResetController {
    @Autowired
    private PasswordResetTokenService tokenService;

    @Autowired
    private UserService userService;

    @GetMapping("/forgot_password")
    public String forgotPassword() {
        return "forgot_password";
    }

    @PostMapping("/forgot_password")
    public String forgotPassword(String email, Model model) {
        User user = userService.findByEmail(email);

        if (user == null) {
            model.addAttribute("errorMsg", "用户不存在");
        } else {
            tokenService.createToken(user);
            model.addAttribute("successMsg", "已发送邮件,请查收");
        }

        return "forgot_password";
    }

    @GetMapping("/reset_password_token")
    public String resetPasswordToken(String token, Model model) {
        PasswordResetToken resetToken = tokenService.findByToken(token);

        if (resetToken == null) {
            model.addAttribute("errorMsg", "重置密码链接已失效");
            return "reset_password_result";
        }

        if (resetToken.isExpired()) {
            model.addAttribute("errorMsg", "重置密码链接已过期");
            return "reset_password_result";
        }

        model.addAttribute("token", token);
        return "reset_password";
    }

    @PostMapping("/reset_password")
    public String resetPassword(String token, String password, Model model) {
        PasswordResetToken resetToken = tokenService.findByToken(token);

        if (resetToken == null) {
            model.addAttribute("errorMsg", "重置密码链接已失效");
            return "reset_password_result";
        }

        if (resetToken.isExpired()) {
            model.addAttribute("errorMsg", "重置密码链接已过期");
            return "reset_password_result";
        }

        User user = resetToken.getUser();
        user.setPassword(new BCryptPasswordEncoder().encode(password));
        userService.save(user);

        model.addAttribute("successMsg", "修改密码成功");
        return "reset_password_result";
    }
}

3.3 重置密码实体类设计

com.example.entity 包下创建 PasswordResetToken 实体类:

@Entity
@Table(name = "t_password_reset_token")
public class PasswordResetToken {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false)
    private User user;

    @Column(unique = true)
    private String token;

    @NotNull
    private Date expiryDate;

    // getter、setter 省略
}

3.4 重置密码服务设计

com.example.service 包下创建 PasswordResetTokenService 重置密码服务:

@Service
public class PasswordResetTokenService {
    @Autowired
    private PasswordResetTokenRepository tokenRepository;

    public PasswordResetToken createToken(User user) {
        PasswordResetToken token = new PasswordResetToken();
        token.setUser(user);
        token.setToken(UUID.randomUUID().toString());
        token.setExpiryDate(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000)); // 设置为 24 小时后过期
        return tokenRepository.save(token);
    }

    public PasswordResetToken findByToken(String token) {
        return tokenRepository.findByToken(token);
    }
}

4. 实现登录功能

4.1 登录控制器设计

com.example.controller 包下创建 SecurityController 控制器:

@Controller
public class SecurityController {
    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @GetMapping("/")
    public String index() {
        return "index";
    }
}

4.2 安全配置类设计

com.example.config 包下创建 SecurityConfig 安全配置类:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/", "/register", "/activate/**", "/forgot_password", "/reset_password_token/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .defaultSuccessUrl("/")
                .and()
            .logout()
                .permitAll();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

5. 示例说明

5.1 注册账号

  1. 访问注册页面:http://localhost:8080/register
  2. 输入邮箱、用户名和密码,点击注册按钮
  3. 到注册邮箱收取激活邮件,并点击邮件里的激活链接
  4. 成功激活后,页面跳转到主页

5.2 忘记密码

  1. 访问忘记密码页面:http://localhost:8080/forgot_password
  2. 输入邮箱,点击发送重置密码邮件
  3. 到注册邮箱收取重置密码邮件,并点击邮件里的重置密码链接
  4. 进入重置密码页面,输入新密码并保存
  5. 成功修改密码后,页面跳转到重置密码结果页面

5.3 登录

  1. 访问登录页面:http://localhost:8080/login
  2. 输入已注册的用户的账号密码,点击登录按钮
  3. 成功登录后,页面跳转到主页

结语

本文详细讲解了如何使用 Spring Boot 实现邮箱验证码注册与修改密码及登录功能,主要包括用户实体类设计、邮箱发送、注册控制器设计、重置密码实体类设计、重置密码服务设计、登录控制器设计以及安全配置类设计。通过本文的学习,可以快速掌握这些功能的实现流程,有助于提高开发效率。

本文标题为:Springboot实现邮箱验证码注册与修改密码及登录功能详解流程

基础教程推荐