Springboot+Vue 邮件找回密码

该文章介绍了如何配置和使用SpringBoot集成Redis来发送邮件,以及前端如何处理密码重置流程。用户输入邮箱获取验证码,后端生成验证码存储在Redis中,并发送邮件,前端验证验证码后重置密码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前期准备:

1、下载安装redis

在这里附上我自己用的redis版本,用其他版本的可以自己去找资源,百度网盘链接:https://pan.baidu.com/s/1WPAksWV-Vi8vDZz_i2YI5w 
提取码:ovxd

首先解压到一个文件,然后双击redies-server.exe即可运行redis。

2、添加依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

3、准备一个邮件.

1、我使用的是163,找到设置,点击POP3这里。

 2、开启这两项服务,记住弹出的一串大写字母,后面要配置的。

往下拉还有服务器地址,配置的时候赋值给host

二、后端配置

在application.properties中配置

# 配置邮箱服务器,账号密码等
spring.mail.host=smtp.163.com

spring.mail.username= XXXXXXXXX@163.com
spring.mail.password= XXXXXXXXXXXX(授权码)

redis用的默认配置,没有额外配。

如果你的配置文件是application.yml,那么使用如下代码配置

# 配置邮箱服务器,账号密码等
spring:
  mail:
    host: smtp.163.com
    username: XXXXXXXX@163.com
    password: XXXXXXXXXXXX(授权码)

三、前端代码

点击忘记密码后跳转忘记密码页面。忘记密码页面及代码如下:

<template>
  <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="auto" class="login-container"
           :hide-required-asterisk="true">
    <h3 class="login_title">重置密码</h3>
    <el-form-item label="用户名:" prop="username">
      <el-input v-model="ruleForm.username"></el-input>
    </el-form-item>
    <el-form-item label="验证码:" prop="code">
      <el-row>
      <el-col span="16"><el-input type="code" v-model="ruleForm.code"></el-input></el-col>
        <el-col span="6"><el-button style="background: #13bbf4; color: #ffffff" :loading="ruleForm.loading"
                 @click="getCode">获取验证码
      </el-button></el-col>
      </el-row>
    </el-form-item>
    <el-form-item label="密 码:" prop="password">
      <el-input type="password" v-model="ruleForm.password" autocomplete="off" show-password></el-input>
    </el-form-item>
    <el-form-item label="确认密码:" prop="password">
      <el-input type="password" v-model="ruleForm.checkPassword" autocomplete="off" show-password></el-input>
    </el-form-item>

    <el-form-item>
      <el-button style="width: 100%; background: #13bbf4; color: #ffffff" :loading="ruleForm.loading"
                 @click="resetPassword">重置密码
      </el-button>
    </el-form-item>
  </el-form>
</template>

<script>
import {ElMessage} from "element-plus";
import {ResetPassword} from "@/api/user";
import router from "@/router";
import {GetCode} from "@/api/mail";

export default {
  name: "ForgetPassword",
  data() {
    return {
      ruleForm: {
        loading: false,
        username: '',
        password: '',
        checkPassword: '',
        code: '',
      },
      rules: {
        username: [
          {required: true, message: '请输入用户名', trigger: 'blur'},
          {min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur'}
        ],
        password: [
          {required: true, message: '请输入密码', trigger: 'blur'},
          {min: 5, max: 11, message: '长度在 5 到 11 个字符', trigger: 'blur'}
        ],
        code: [
          {required: true, message: '请输入验证码', trigger: 'blur'},
        ],
      }
    }
  },
  methods: {
    getCode(){
      this.$refs["ruleForm"].validateField('username',valid=>{
        if(valid){
          GetCode(this.ruleForm.username).then(res=>{
            if(res.code===200){
              this.$message({
                type:'success',
                message:'验证码已发送'
              })
            }
          })
        }
      })
    },
    resetPassword() {
      this.$refs['ruleForm'].validate(valid=>{
        if(valid){
          if (this.ruleForm.password !== this.ruleForm.checkPassword) {
            return ElMessage('您两次输入的密码不同')
          }

          const data = {
            username: this.ruleForm.username,
            password: this.ruleForm.password,
            code:this.ruleForm.code
          };


          this.ruleForm.loading = true
          ResetPassword(data).then(res => {
            console.log(res)
            if (res.code === 200) {
                this.ruleForm.loading = false;
                router.push("/userLogin")
                this.$message({
                  type:'success',
                  message:'重置成功'
                })
            } else {
              setTimeout(() => {
                this.ruleForm.loading = false;
                this.$message({
                  type:'error',
                  message:'重置失败'
                })
              }, 1000)
            }
          }, () => this.ruleForm.loading = false)
        }
      })


    }
  }
}
</script>

<style scoped>

.login_title {
  margin: 0 auto 40px auto;
  text-align: center;
  color: #505458;
}

.login-form-footer {
  font-weight: bolder;
  color: #91949c;
  text-align: center;
}

.login-container {
  border-radius: 15px;
  background-clip: padding-box;
  margin: 70px auto;
  width: 450px;
  height: 400px;
  background: #fff;
  padding: 15px 15px 15px 15px;
  border: 1px solid #eaeaea;
  box-shadow: 0 0 25px #cac6c6;
  text-align: center;
}

body {
  margin: 0;
}

.login_title {
  margin: 0px auto 40px auto;
  text-align: center;
  color: #505458;
}

el-checkbox {
  color: #91949c;
  font-weight: bolder;
  font-size: 15px;
}
</style>

js文件封装方法:

export function GetCode(username){
    return service({
        url: '/mail'+'/'+username,
        method: 'get',
    })
}

export function ResetPassword(data){
    return service({
        url:'/user/forget',
        method:'post',
        data:data
    })
}

四、后端代码

1、MailService 

public interface MailService {
    void getCode(String username) throws Exception;
}

2、MailServiceImpl



import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lxj.siweiboot.mapper.UserMapper;
import com.lxj.siweiboot.model.entity.User;
import com.lxj.siweiboot.service.MailService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 用户邮件相关
 */
@Service
public class MailServiceImpl implements MailService {

    private final String MAIL = "MAIL" ;

    private int timeout = 5;

    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private JavaMailSender javaMailSender;

    @Override
    public void getCode(String username) throws Exception  {
        //验证用户名与邮件是否匹配
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("username",username);
        User u = userMapper.selectOne(queryWrapper);
        if(u == null){
            throw new Exception("用户名不存在");
        }
        String mail = u.getEmail();
        String verifyCode = String.valueOf(new Random().nextInt(9999));
        redisTemplate.opsForValue().set(MAIL+username,verifyCode,timeout, TimeUnit.MINUTES);

        // 编写邮箱内容
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<html><head><title></title></head><body>");
        stringBuilder.append("  您好<br/>");
        stringBuilder.append("  您的验证码是:").append(verifyCode).append("<br/>");
        stringBuilder.append("  您可以复制此验证码并返回系统找回密码页面,以验证您的邮箱。<br/>");
        stringBuilder.append("  此验证码只能使用一次,在");
        stringBuilder.append(timeout);
        stringBuilder.append("  分钟内有效。验证成功则自动失效。<br/>");
        stringBuilder.append("  如果您没有进行上述操作,请忽略此邮件。");
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();

        // 发件配置并发送邮件
        try {
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
            //这里只是设置username 并没有设置host和password,因为host和password在springboot启动创建JavaMailSender实例的时候已经读取了
            mimeMessageHelper.setFrom("XXXXXXXXX@163.com");
            mimeMessageHelper.setTo(mail);
            mimeMessage.setSubject("邮箱验证-重置密码");
            mimeMessageHelper.setText(stringBuilder.toString(), true);
            javaMailSender.send(mimeMessage);
            System.out.println("email");
        } catch (MessagingException e) {
            e.printStackTrace();
        }

    }
}

3、MailController

import com.lxj.siweiboot.service.MailService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@CrossOrigin("*")
@RestController
@RequestMapping("/api/mail")
public class MailController {
    @Resource
    private MailService mailService;
    @GetMapping("/{username}")
    public void getCode(@PathVariable String username) throws Exception {
        mailService.getCode(username);
    }
}

4、UserServiceImpl 

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    RedisTemplate redisTemplate;

    @Override
    public void resetPassword(ResetPwDto dto) throws Exception {
        String username = dto.getUsername();
        String code = dto.getCode();
        String redisCode = (String) redisTemplate.opsForValue().get("MAIL"+username);
        System.out.println("redisCode"+redisCode);
        if(redisCode==null|| !redisCode.equals(code)) throw new Exception("验证码错误");
        String password = dto.getPassword();
        QueryWrapper<User> queryWrapper =new QueryWrapper<>();
        queryWrapper.in("username",username);
        User u = userMapper.selectOne(queryWrapper);
        u.setPassword(bCryptPasswordEncoder.encode(password));
        userMapper.updateById(u);
    }
}

5、UserController

@CrossOrigin("*")
@RestController
@RequestMapping("/api/user")
public class UserController {
    @Resource
    private UserService userService;

    @PostMapping("/forget")
    public void resetPassword(@RequestBody ResetPwDto dto) throws Exception {
        userService.resetPassword(dto);
    }
}

以上,部分参考基于SpringBoot实现邮箱找回密码 - 小张吖 - 博客园 (cnblogs.com)

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值