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

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实现邮箱验证码注册与修改密码及登录功能详解流程 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • 动态加载JS文件的三种方法

    下面是详细讲解“动态加载JS文件的三种方法”的完整攻略。 引言 在网站开发中,动态加载JS文件是一个很常见的需求。因为动态加载JS文件可以让网页更加灵活,可以根据特定条件来加载特定JS文件,从而避免不必要的JS文件加载和性能消耗。在本文中,我们将介绍动态加载JS文件的三种方法。 方法一:createElement() 方法 createElement() 方…

    JavaScript 2023年5月27日
    00
  • js中数组对象去重的两种方法

    讲解“js中数组对象去重的两种方法”的完整攻略。 1.方法1:使用Set JavaScript中的Set是一种可以存储不重复值的集合。因此,可以通过Set来去重。 示例代码 const arr = [{id:1,name:’test’},{id:2,name:’test’},{id:1,name:’test’}] const newArr = Array.f…

    JavaScript 2023年5月27日
    00
  • javascript 进阶篇1 正则表达式,cookie管理,userData

    JavaScript 进阶篇1:正则表达式、Cookie 管理、UserData 1. 正则表达式 正则表达式在 JavaScript 开发中非常重要,是处理字符串的得力工具。以下是一些基本概念和正则表达式在 JavaScript 中的应用。 基本概念 匹配模式:正则表达式在搜索时所用的模式 字符串搜索:在文本中搜索匹配模式并返回匹配结果 模式修饰符:使用标…

    JavaScript 2023年6月11日
    00
  • 前端token中4个存储位置的优缺点说明

    前端Token是指存储在前端网页中的用来标识用户身份的令牌,一般用于用户登录、验证和权限控制等方面。前端Token可以存在多个存储位置中,通常有四种:Cookie、Web Storage、IndexedDB、Memory。 以下是关于这四个存储位置的优缺点说明: Cookie Cookie是HTTP协议中常用的一种存储方式,可以存放在客户端的浏览器中,也可以…

    JavaScript 2023年6月11日
    00
  • canvas实现粒子时钟效果

    下面是“canvas实现粒子时钟效果”的完整攻略: 步骤一:设置画布 首先需要在HTML文件中添加一个canvas标签,并设置其宽高。如下面的示例代码所示: <canvas id="canvas" width="600" height="600"></canvas> 接着,在…

    JavaScript 2023年6月11日
    00
  • 详解JavaScript对象转原始值

    回答: 1. JavaScript对象转原始值 在JavaScript中,当一个对象被转换成原始类型时,会调用该对象的valueOf()和toString()方法。如果这两个方法都不存在或没有返回原始值,则会抛出TypeError异常。 1.1 valueOf()方法 对于大多数JavaScript对象,valueOf()方法会返回对象本身。但是对于包装对象…

    JavaScript 2023年5月27日
    00
  • 网页实时显示服务器时间和javscript自运行时钟

    实时显示服务器时间和JavaScript自运行时钟,是网页中经常用到的两个功能。下面我将为您介绍实现这两个功能的完整攻略。 实时显示服务器时间 实时显示服务器时间,我们需要通过向服务器发送请求来获得服务器时间,然后使用JavaScript将服务器时间实时显示在网页中。下面是实现步骤。 步骤一:通过ajax向服务器获取时间 在JavaScript中使用ajax…

    JavaScript 2023年5月27日
    00
  • Dom-api MutationObserver使用方法详解

    Dom-api MutationObserver使用方法详解 概述 MutationObserver是Web API中的一个对象,用于监视DOM树中发生的变化,并提供回调函数,用于在变化发生时执行相应逻辑。 基本用法 MutationObserver的基本用法如下 // 创建一个观察器实例并指定回调函数 const observer = new Mutati…

    JavaScript 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部