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

yizhihongxing

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私有作用域中创建特权方法

    下面我将详细讲解如何在 JavaScript 的私有作用域(闭包)中创建特权方法,希望能对你有所帮助。 什么是特权方法? 在 JavaScript 中,特权方法指的是可以访问私有作用域中成员的公有方法。通常情况下,私有作用域中的成员对于外界来说是不可见的,但是通过特权方法,我们可以将私有作用域中的成员暴露出来,以便外界调用和使用。 如何创建特权方法? 创建特…

    JavaScript 2023年6月10日
    00
  • 如何使用JavaScript快速创建一个1到100的数组

    下面是使用JavaScript快速创建1到100的数组的攻略: 1. 使用for循环快速创建一个1到100的数组 // 创建一个长度为 100 的数组 var arr = new Array(100); for (var i = 0; i < arr.length; i++) { // 把数组的每个元素赋值为它的下标+1 arr[i] = i + 1;…

    JavaScript 2023年5月27日
    00
  • 不要小看注释掉的JS 引起的安全问题

    首先,注释掉的 JavaScript 代码是存在安全问题的,因为这些代码可以被黑客利用来进行攻击。因此,我们需要小心处理这些注释掉的代码。下面是一些攻略: 1. 审查代码,删除无用的注释信息 我们应该定期地审查我们的代码,删除无用的注释信息。在代码中注释掉的代码可能是过时的,已被修复或已不再需要。除此之外,注释信息还可能包含敏感信息,比如数据库密码、API …

    JavaScript 2023年6月11日
    00
  • 微信小程序 生命周期和页面的生命周期详细介绍

    下面详细讲解一下微信小程序的生命周期和页面的生命周期: 微信小程序生命周期介绍 微信小程序生命周期分为两个部分:全局生命周期和页面生命周期。全局生命周期是指在整个小程序中被执行的方法,而页面生命周期则是指在页面中被执行的方法。 全局生命周期 全局生命周期包含以下方法: 1. onLaunch(options) 在小程序初始化完成时执行,只会执行一次。 参数说…

    JavaScript 2023年6月11日
    00
  • JavaScript代码应该放在HTML代码哪个位置比较好?

    当我们编写JavaScript代码时,应该考虑将其放在HTML中的哪个位置。这样可以提高网站性能、可维护性和可靠性。 一般来说,可以将JavaScript代码放在HTML文档的头部或尾部,或者在文档中间使用异步加载。下面分别介绍这三种放置JavaScript代码的方式。 1.头部 将JavaScript代码放在头部,可以确保所有代码都被下载和解释,但是可能会…

    JavaScript 2023年5月27日
    00
  • jQuery.cookie.js使用方法及相关参数解释

    jQuery.cookie.js使用方法及相关参数解释 简介 jQuery.cookie.js 是一个轻量级的jQuery插件,用于方便地读取、写入和删除Cookies。本攻略将详细介绍该插件的使用方法及参数解释。 安装 首先需要引入 jQuery 库,然后将 jquery.cookie.js 引入到 HTML 页面中。 <script src=&qu…

    JavaScript 2023年6月11日
    00
  • js字符串与Unicode编码互相转换

    JavaScript字符串与Unicode编码互相转换 JavaScript内部使用Unicode编码,每个字符对应一个Unicode码位,可以通过字符串和Unicode编码之间的互相转换来操作Unicode码位。 字符串转Unicode编码 字符串转换成Unicode编码可以使用JavaScript内置的charCodeAt()函数。 charCodeAt…

    JavaScript 2023年5月20日
    00
  • 深入剖析JavaScript中的函数currying柯里化

    深入剖析JavaScript中的函数currying柯里化 什么是柯里化? 柯里化 (Currying),又称部分求值 (Partial Evaluation),是一种把接收多个参数的函数变换成接收一个单一参数 (最初函数的第一个参数) 的函数,并返回一个新函数的过程。新函数接收余下的参数,并返回原函数需要返回的结果。 举个例子,下面这个简单的函数: fun…

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