VUE+SPRINGBOOT实现邮箱注册、重置密码、登录功能

随着互联网的发展,网站用户的管理、触达、消息通知成为一个网站设计是否合理的重要标志。目前主流互联网公司都支持手机验证码注册、登录。但是手机短信作为服务端网站是需要付出运营商通信成本的,而邮箱的注册、登录、重置密码,无疑成为了这一问题的最佳解决方案,那么如何通过VUE+SPRINGBOOT实现邮箱网站用户的注册、登录、重置密码呢?下面直接说明效果和代码实现。体验网址点击可以访问:whiteicon-default.png?t=O83Ahttps://wdfgdzx.top/login

一、VUE注册界面,核心逻辑在邮箱正则验证+邮箱验证码发送与存储。

<template>
  <div class="Register-container">
    <div class="allClass">
      <div class="titleClass"><b>没有账号请邮箱注册</b></div>

      <el-form :rules="ruleList" :model="user" ref="userForm"><!--用来校验表单-->

        <el-form-item prop="name"><!--必须el-form-item prop="xxx"才能生效-->
          <el-input placeholder="请输入您的邮箱" size="medium" class="inputOneClass" prefix-icon="el-icon-message"
                    v-model="user.name" autocomplete="new-password"></el-input>
        </el-form-item>

        <el-form-item prop="code"><!--邮箱获取的验证码,放置非法注册-->
          <el-input placeholder="邮箱收到的验证码" size="medium" class="inputOneClass" prefix-icon="el-icon-lock"
                    v-model="user.code" style="width: 188px;"></el-input>
          <el-button type="primary" size="medium" class="ml-10" @click="getEmailCode">获取验证码</el-button>
        </el-form-item>

        <el-form-item prop="password">
          <el-input placeholder="请设置密码" size="medium" class="inputOneClass" prefix-icon="el-icon-lock"
                    v-model="user.password"
                    show-password autocomplete="new-password"></el-input>
        </el-form-item>


        <div class="buttonClass">
          <el-button type="primary" size="medium" autocomplete="off" @click="registerClick">注册用户</el-button>
          <el-button type="warning" size="medium" autocomplete="off" @click="$router.push('/login')">返回登录
          </el-button>
        </div>
      </el-form>

    </div>
  </div>
</template>

<script>
export default {
  name: "Register",
  data() {
    return {
      user: {},
      ruleList: { // 在return的第一级别写
        name: [
          {required: true, message: '请输入您的邮箱账号', trigger: 'blur'},
          {min: 3, max: 20, message: '长度在3-9个字符', trigger: 'blur'}
        ],
        password: [
          {required: true, message: '请设置密码', trigger: 'blur'},
          {min: 3, max: 20, message: '长度在3-20个字符', trigger: 'blur'}
        ],
        code: [
          {required: true, message: '请输入收到的验证码', trigger: 'blur'},
          {min: 3, max: 20, message: '长度在3-20个字符', trigger: 'blur'}
        ]
      }
    }
  },
  methods: {
    getEmailCode() {
      if (!this.user.name) {
        this.$message.warning("请输入邮箱账号")
        return
      }
      if (!/^\w+((.\w+)|(-\w+))@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+).[A-Za-z0-9]+$/.test(this.user.name)) {
        this.$message.warning("请输入正确的邮箱账号")
        return
      }
      // 都通过请求发送邮箱验证码---name的值其实就是用户邮箱
      this.$http.post("/big/email_code", this.user).then(res => {
        if (res.data.code === "200") {
          this.$message.success("邮箱验证码发送成功,请到对应邮箱查看")
        } else {
          this.$message.error(res.data.message)
        }
      })
    },
    /*点击登录*/
    registerClick() {
      this.$refs["userForm"].validate(valid => {
        if (valid) { // 表单校验合法
          this.$http.post("/big/register", this.user).then(res => { // 调用后端注册方法
            // console.log(res.data)
            if (res.data.code === "200") {
              this.$router.push("/login")
              this.$message.success("注册成功,请登录!")
            } else {
              this.$message.error(res.data.message)
            }
          });
        }
      })
    }
  }
}
</script>

<style scoped>
.Register-container {
  height: 100vh;
  background-image: linear-gradient(to bottom right, deepskyblue, darkcyan);
  overflow: hidden;
}

.allClass {
  margin: 200px auto;
  background-color: #ffffff;
  width: 350px;
  height: 400px;
  padding: 20px;
  border-radius: 10px;
}

.titleClass {
  margin: 20px 0;
  text-align: center;
  font-size: 24px;
}

.inputOneClass {
  margin: 10px 0;
}

.buttonClass {
  margin: 10px 0;
  text-align: right;
}
</style>

二、后端发送与存储逻辑

@PostMapping("/email_code") // 也需要配置可以直接访问
    public Res email_code(@RequestBody User user) {
        if (StringUtils.isBlank(user.getName())) {
            return Res.error(Constants.CODE_400, "参数错误");
        }
        QueryWrapper<Email> emailQueryWrapper = new QueryWrapper<>();
        emailQueryWrapper.eq("email", user.getName());
        Email existEmail = emailMapper.selectOne(emailQueryWrapper);
        Date nowTime = new Date();
        long diffLongTime = 0L;
        if (existEmail != null && existEmail.getSendTime() != null) { // 首次注册必为空
            diffLongTime = nowTime.getTime() - existEmail.getSendTime().getTime(); // 所以如果为空则直接放行,不为空在这里获取时间差距
            if (diffLongTime <= (5 * 60 * 1000)) {
                return Res.error(Constants.CODE_600, "您的验证码5分钟内有效,请到您的邮箱查看验证码,或者请您5分钟后再获取。");
            }
        }
        // 发送邮箱验证码
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        simpleMailMessage.setFrom("wdfgdzx@126.com"); // 这个发件人必须设置,和配置的一样
        Date sendDate = new Date();
        simpleMailMessage.setSentDate(sendDate);
        simpleMailMessage.setSubject("【人人都有人工智能注册验证码】");
        String code = RandomUtil.randomNumbers(4);
        simpleMailMessage.setText("您本次邮箱注册的验证码是:【" + code + "】,请妥善保管,切勿泄露。");
        simpleMailMessage.setTo(user.getName()); // 用户输入的邮箱
        Email emailEntity = new Email();
        emailEntity.setEmail(user.getName());
        emailEntity.setCode(code);
        emailEntity.setSendTime(sendDate);
        if (existEmail == null) { // 验证码存储与更新逻辑
            emailMapper.insert(emailEntity); // 不存在则插入
        } else {
            emailMapper.update(emailEntity, emailQueryWrapper); // 存在则升级code,根据邮箱名称升级
        }
        javaMailSender.send(simpleMailMessage);
        return Res.success(null); // 返回200即可
    }

    @PostMapping("/register")
    public Res register(@RequestBody User user) {
        User existUser;
        // 比对验证码
        QueryWrapper<Email> emailQueryWrapper = new QueryWrapper<>();
        emailQueryWrapper.eq("email", user.getName());
        Email existEmail = emailMapper.selectOne(emailQueryWrapper);
        if (existEmail != null && !existEmail.getCode().equals(user.getCode())) {
            // System.err.println(existEmail.getCode());
            // System.err.println(existEmail.getCode() == null);
            if (existEmail.getCode().isEmpty()) {
                return Res.error(Constants.CODE_600, "验证码已经失效,请重新获取验证码");
            } else {
                return Res.error(Constants.CODE_600, "验证码验证失败,请检查验证码是否填写正确");
            }
        }
        if (existEmail != null && (existEmail.getCode() != null)) {
            existEmail.setCode("");
            emailMapper.updateById(existEmail);
        }
        try {
            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
            userQueryWrapper.eq("name", user.getName());
            existUser = userMapper.selectOne(userQueryWrapper); // 新技术
            // existUser = userMapper.selectUserByName(user);
        } catch (Exception e) { // 如果系统中存在多条等异常情况
            e.printStackTrace();
            return Res.error(Constants.CODE_500, "系统错误");
        }
        if (existUser != null) {
            return Res.error(Constants.CODE_600, "用户名已经存在,请更换用户名");
        }
        user.setNick("人工智能-热爱者"); // 默认的昵称
        user.setRole("人工智能"); // 默认角色
        user.setPassword(MyUtils.getSHA256StrJava(user.getPassword())); // 密码用SHA256加密存储
        user.setAvatar("https://wdfgdzx.top:3333/document/cd39af3e175b4524890c267e07298f5b.png"); // 设置默认头像,这个每次需要变动的 发布V1.0后再修改
        userMapper.insert(user); // 不存在,开始插入到数据库
        return Res.success(null); // 返回200即可
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/917903.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络基础(4)传输层

既然是传输层首先就要明确实在层状结构的哪里,除开物理层之外分成了四层协议: 到这里上层(应用层)的使用已经没有问题&#xff0c;之前使用的套接字都是在应用层的。 再说端口号 到一个主机收到一个报文的时候&#xff0c;这个报文中一定存在这个报文需要到的主机的ip号。如果…

web——sqliabs靶场——第六关——报错注入和布尔盲注

这一关还是使用报错注入和布尔盲注 一. 判断是否有sql注入 二. 判断注入的类型 是双引号的注入类型。 3.报错注入的检测 可以使用sql报错注入 4.查看库名 5. 查看表名 6.查看字段名 7. 查具体字段的内容 结束 布尔盲注 结束

网络基础 - 网段划分篇

我们知道&#xff0c;IP 地址(IPv4 地址)由 “网络标识(网络地址)” 和 “主机标识(主机地址)” 两部分组成&#xff0c;例如 192.168.128.10/24&#xff0c;其中的 “/24” 表示从第 1 位开始到多少位属于网络标识&#xff0c;那么&#xff0c;剩余位就属于主机标识了&#xf…

【AI图像生成网站Golang】JWT认证与令牌桶算法

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 三、JWT认证与令牌桶算法 在现代后端开发中&#xff0c;用户认证和接口限流是确保系统安全性和性能的两大关键要素…

TR3:Pytorch复现Transformer

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、实验目的 从整体上把握Transformer模型&#xff0c;明白它是个什么东西&#xff0c;可以干嘛读懂Transformer的复现代码 二、实验环境 语言环境&#xff1…

数据分布之指数分布(sample database classicmodels _No.10)

数据分布之指数分布&#xff08;sample database classicmodels _No.10&#xff09; 准备工作&#xff0c;可以去下载 classicmodels 数据库具体如下 点击&#xff1a;classicmodels 也可以去 下面我的博客资源下载 https://download.csdn.net/download/tomxjc/88685970 文章…

无人机动力系统测试-实测数据与CFD模拟仿真数据关联对比分析

我们经常被问到这样的问题&#xff1a;“我们计划运行 CFD 仿真&#xff0c;我们还需要对电机和螺旋桨进行实验测试吗&#xff1f;我们可能有偏见&#xff0c;但我们的答案始终是肯定的&#xff0c;而且有充分的理由。我们自己执行了大量的 CFD 仿真&#xff0c;但我们承认&…

MinIO 的 S3 over RDMA 计划: 为高速人工智能数据基础设施设定对象存储新标准

随着 AI 和机器学习的需求不断加速&#xff0c;数据中心网络正在迅速发展以跟上步伐。对于许多企业来说&#xff0c;400GbE 甚至 800GbE 正在成为标准选择&#xff0c;因为数据密集型和时间敏感型 AI 工作负载需要高速、低延迟的数据传输。用于大型语言处理、实时分析和计算机视…

游戏引擎学习第13天

视频参考:https://www.bilibili.com/video/BV1QQUaYMEEz/ 改代码的地方尽量一张图说清楚吧,懒得浪费时间 game.h #pragma once #include <cmath> #include <cstdint> #include <malloc.h>#define internal static // 用于定义内翻译单元内部函数 #…

十分钟学会html超文本标记语言

前言 本次学习的是在b站up主泷羽sec课程有感而发&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 &#xff01;&#xff01;…

【Linux系统编程】第四十七弹---深入探索:POSIX信号量与基于环形队列的生产消费模型实现

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、POSIX信号量 2、基于环形队列的生产消费模型 2.1、代码实现 2.1.1、RingQueue基本结构 2.1.2、PV操作 2.1.3、构造析构…

除了 TON, 哪些公链在争夺 Telegram 用户?数据表现如何?

作者&#xff1a;Stella L (stellafootprint.network) 在 2024 年&#xff0c;区块链游戏大规模采用迎来了一个意想不到的催化剂&#xff1a;Telegram。随着各大公链争相布局这个拥有海量用户基础的即时通讯平台&#xff0c;一个核心问题浮出水面&#xff1a;这种用户获取策略…

小白进!QMK 键盘新手入门指南

经常玩键盘的伙伴应该都知道&#xff0c;现在的键盘市场可谓是百花齐放&#xff0c;已经不是之前的单一功能产品化时代。我们可以看到很多诸如&#xff1a;机械轴键盘、磁轴键盘、光轴键盘、电感轴键盘&#xff0c;以及可能会上市的光磁轴键盘&#xff0c;更有支持屏幕的、带旋…

【HarmonyOS】鸿蒙系统在租房项目中的项目实战(二)

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…

《Markdown语法入门》

文章目录 《Markdown语法入门》1.标题2.段落2.1 换行2.2分割线 3.文字显示3.1 字体3.2 上下标 4. 列表4.1无序列表4.2 有序列表4.3 任务列表 5. 区块显示6. 代码显示6.1 行内代码6.2 代码块 7.插入超链接8.插入图片9. 插入表格 《Markdown语法入门》 【Typora 教程】手把手教你…

北京大学c++程序设计听课笔记101

基本概念 程序运行期间&#xff0c;每个函数都会占用一段连续的内存空间。而函数名就是该函数所占内存区域的起始地址&#xff08;也称“入口地址”&#xff09;。我们可以将函数的入口地址赋给一个指针变量&#xff0c;使该指针变量指向该函数。然后通过指针变量就可以调用这个…

C++:boost库安装

官网&#xff1a;https://www.boost.org/ Boost 库在 C 社区中广受欢迎&#xff0c;主要因为它提供了丰富、强大且稳定的功能&#xff0c;可以显著提高开发效率和代码质量。下面是使用 Boost 库的主要优势和特点&#xff1a; 1. 丰富的功能集合 Boost 提供了数十个高质量的 …

VScode学习前端-01

小问题合集&#xff1a; vscode按&#xff01;有时候没反应&#xff0c;有时候出来&#xff0c;是因为------>必须在英文状态下输入&#xff01; 把鼠标放在函数、变量等上面&#xff0c;会自动弹出提示&#xff0c;但挡住视线&#xff0c;有点不习惯。 打开file->pre…

机房动环境监控用各种列表已经淘汰了,现在都是可视化图表展示了

在信息技术飞速发展的今天&#xff0c;机房作为数据存储、处理和传输的核心场所&#xff0c;其稳定运行至关重要。过去&#xff0c;机房动环境监控主要依赖各种列表形式来呈现数据&#xff0c;但如今&#xff0c;这种方式已经逐渐被淘汰&#xff0c;取而代之的是更加直观、高效…

Pytest-Bdd-Playwright 系列教程(10):配置功能文件路径 优化场景定义

Pytest-Bdd-Playwright 系列教程&#xff08;10&#xff09;&#xff1a;配置功能文件路径 & 优化场景定义 前言一、功能文件路径的配置1.1 全局设置功能文件路径1.2. 在场景中覆盖路径 二、避免重复输入功能文件名2.1 使用方法2.2 functools.partial 的背景 三、应用场景总…