使用邮箱发送验证码前端完成登录

前言

在前一篇使用C#发送邮箱验证码已经完成使用.net core web api写了完成往登录邮箱发送验证码的接口。现在就用前端调用接口模拟登录功能。

接口

 public class ApiResp
 {
     public bool Success { get; set; }
     public int Code { get; set; }
     public int  count { get; set; }
     public string msg { get; set; }
     public object Data { get; set; }
 }
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Model;
using System.IO;

namespace TestSystem.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        [HttpPost]
        public ApiResp email(string username,string email)
        {
          var resp = new ApiResp();
            if (username == "admin")//模拟数据库读取 UserName是唯一属性
            {
                EmaliSend e = new EmaliSend();
                string str = e.emailsendone(email);
                resp.Data = str;
                resp.Success = true;
                return resp;
            }
            resp.Success = false;
            return resp;
        }
    }
}

前端

前端使用是layui样式+Vue写的功能。
在这里插入图片描述

引入Vue

记得把<div id = "app"></div>把前端样式包含

	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
	<div class="layui-form-item" v-if="vercodeVisible">
							<div class="layui-form-item">
								<label class="layadmin-user-login-icon layui-icon layui-icon-email"
									for="LAY-user-login-email"></label>
								<input type="text" name="email" v-model="email" placeholder="请输入邮箱" autocomplete="off"
									class="layui-input">
							</div>
							<div class="layui-row">
								<div class="layui-col-xs7">
									<label class="layadmin-user-login-icon layui-icon layui-icon-vercode"
										for="LAY-user-login-vercode"></label>
									<input type="text" name="vercode" id="LAY-user-login-vercode" lay-verify="required"
										v-model="emalistr" placeholder="验证码" class="layui-input">
								</div>
								<div class="layui-col-xs5">
									<div style="margin-left: 10px;">
										<button type="button" class="layui-btn layui-btn-primary layui-btn-fluid"
											@click="EmailSend" id="emailButton">获取验证码</button>
									</div>
								</div>
							</div>
						</div>	
						<div class="layui-form-item">
							<button class="layui-btn layui-btn-fluid" v-if="vercodeVisible" lay-submit
								lay-filter="LAY-user-login-submit" @click="loginEmail">验证码登录
							</button>		
						</div>

Vue写调用发送邮箱api

<script>
			// 提前引入layui并初始化layer模块
			layui.use('layer', function() {
				var layer = layui.layer;
				new Vue({
					el: '#app',
					data: {
						username: 'admin',
						email: 'xx@163.com', //邮箱
						emalistr: '', //邮箱验证码
						remalistr: '', //缓存邮箱验证码
					},
					mounted() {

					},
					methods: {
						EmailSend() {
							const button = document.getElementById('emailButton'); // 获取按钮元素
							const originalText = button.innerText; // 原始按钮文本
							const username = this.username;
							const email = this.email;

							// 邮箱格式验证正则表达式
							const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
							if (!emailRegex.test(email)) {
								layer.msg('请输入正确的邮箱地址', {
									time: 1000,
									icon: 5,
									shade: [0.5, '#000'],
									shadeClose: true
								});
								return; // 邮箱格式不正确,停止执行发送邮件操作
							}
							const headers = new Headers();
							headers.append('Content-Type', 'application/json');
							const body = JSON.stringify({
								username,
								email
							});

							button.disabled = true; // 禁用按钮
							let countDown = 60; // 倒计时时间

							const timer = setInterval(() => {
								if (countDown >= 1) {
									button.innerText = `${countDown}秒后可重发`; // 更新按钮文本
									countDown--;
								} else {
									clearInterval(timer);
									button.innerText = originalText; // 还原按钮文本
									button.disabled = false; // 启用按钮
								}
							}, 1000);

							fetch('https://localhost:44301/api/Login/EmaliSendLogin', {
									method: 'POST',
									headers: headers,
									body: body
								})
								.then(response => response.json())
								.then(data => {
									if (data.success) {
										layer.msg('发送成功', {
											time: 500,
											icon: 6,
											shade: [0.5, '#000'],
											shadeClose: true,
											end: function() {
												console.log("验证码" + data.data);
												localStorage.setItem('remalistr', data.data);
											}

										});
									} else {
										layer.msg('发送失败', {
											time: 1000,
											icon: 5,
											shade: [0.5, '#000'],
											shadeClose: true
										});
									}
								})
								.catch(error => {
								  console.log(error);
								  layer.msg('发送失败,请检查网络连接', {
								    time: 1000,
								    icon: 5,
								    shade: [0.5, '#000'],
								    shadeClose: true
								  });
								});
						},

						loginEmail() {
							const username = this.username;
							const email = this.email;
							const emalistr = this.emalistr;
							const remalistr = localStorage.getItem('remalistr');

							const vercode = this.vercode;
							const operator = this.operator;
							const headers = new Headers();
							headers.append('Content-Type', 'application/json');

							const body = JSON.stringify({
								username,
								email,
							});

							fetch('https://localhost:44301/api/Login/LoginEmail', {
									method: 'POST',
									headers: headers,
									body: body
								})
								.then(response => response.json())
								.then(data => {
									if (data.success && localStorage.getItem('remalistr') === this
										.emalistr && this.vercode == this.rvercode) {
										layer.msg('登录成功', {
											time: 1000,
											icon: 6,
											shade: [0.5, '#000'],
											shadeClose: true,
											end: function() {
												console.log(data.data);

												localStorage.setItem('data', JSON.stringify(data
													.data));
												location.href = '../';
											}
										});
									} else {
										layer.msg('登录失败', {
											time: 1000,
											icon: 5,
											shade: [0.5, '#000'],
											shadeClose: true
										});
									}
								})
								.catch(error => {
									console.log(error);
								});
						},
					}
				});
			});
		</script>

结果

在这里插入图片描述
右侧那验证码是缓存中的验证码,一般是看不见的。

主要逻辑

前端调用后端发送验证码的方法,传入username和邮箱。username是唯一,在数据库不可重复。
后端返回JSON格式给前端,前端解析返回的验证码以及其他用户信息可以进行验证码的读取,然后用户收到邮箱发来的验证码可以进行登录,进行用户输入的验证码和浏览器缓存的验证码进行比对然后登录成功。
还可以添加进行验证码的过期策略以及添加多种验证登录。

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

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

相关文章

20240105-工作安排的最大收益

题目要求 我们有 n 份工作&#xff0c;每份工作都安排在 startTime[i] 至 endTime[i] 期间完成&#xff0c;从而获得 profit[i] 的利润。 给你 startTime、endTime 和 profit 数组&#xff0c;返回你能获得的最大利润&#xff0c;使得子集中没有两个时间范围重叠的工作。 如…

SSH 无密登录配置

1)配置 ssh (1)基本语法 ssh 另一台电脑的 IP 地址 (2)ssh 连接时出现 Host key verification failed 的解决方法 [yuxuan@yuxuan102 ~]$ ssh yuxuan103 ➢ 如果出现如下内容 Are you sure you want to continue connecting (yes/no)? ➢ 输入 yes,并回车 (3)退回到 …

MYSQL 存储过程/存储函数

简而言之&#xff0c;类似于封装函数 特点 基本语法 create peocedure p1() begin select coun(*) from studuent; end; call p1(); 设置完别忘了把delimiter改回来 变量 系统变量 用户自定义变量 set myname its; set myage : 10; 局部变量 if 参数&#xff08;IN&…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)线程池的启动和从线程池中取出一个反应堆实例

一、线程池的启动 &#xff08;主线程&#xff09; // 启动线程池 &#xff08;主线程&#xff09; void threadPoolRun(struct ThreadPool* pool) {/*线程池被创建出来之后&#xff0c;接下来就需要让线程池运行起来&#xff0c;其实就是让线程池里的若干个子线程运行起来*//…

JVM虚拟机的垃圾回收器(面试题)

1.什么是垃圾回收 垃圾回收主要说的是java会自动把程序在运行过程中产生的一些没有用的对象给回收掉&#xff0c;这样可以避免内存的浪费。 java主要是通过一个叫“根可达”的算法来识别这个对象是否可以被回收的&#xff0c;然后回收的算法也主要有三种&#xff1a;标记清除&a…

Python 教程 02:Python 编程环境的搭建与 IDE 的选择

目录 一、搭建 Python 环境 1.1 Python 官网 1.2 下载 Python 1.2.1 选择版本 1.2.2 选择平台 1.2.3 下载安装文件&#xff08;Windows & macOS&#xff09; 1.3 安装环境 1.3.1 Windows 平台 1.3.2 macOS 平台 1.3.3 Linux 平台 1.4 验证安装是否成功 二、选择…

Flink自定义Source模拟数据流

maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.…

瓢虫目标检测数据集VOC格式400张

瓢虫&#xff0c;一种小巧玲珑、色彩鲜艳的昆虫&#xff0c;因其独特的形态和生态习性而受到广泛欢迎。 瓢虫的体型小巧&#xff0c;一般为圆球形&#xff0c;体色鲜艳&#xff0c;有红、黄、黑等多种颜色。它们通常有一个坚硬的外壳&#xff0c;可以保护自己不受天敌的侵害。…

12月笔记

#pragma once 防止多次引用头文件&#xff0c;保证同一个&#xff08;物理意义上&#xff09;文件被多次包含&#xff0c;内容相同的两个文件同样会被包含。 头文件.h与无.h的文件&#xff1a; iostream是C的头文件&#xff0c;iostream.h是C的头文件&#xff0c;即标准的C头文…

前端--基础 常用标签 - 超链接标签 ( 内部链接,空链接,下载链接,网页元素连接)

链接分类 &#xff1a; 外部链接 内部链接 空链接 下载链接 网页元素链接 内部链接 &#xff1a; 即 网站内部页面之间的相互链接&#xff0c;直接点击 链接内部页面名称即可 所谓内部链接&#xff0c;就是在同一个网站里面&#xff0c;有许多链接&#xff0c;当你在 a…

机器学习笔记 - 用于语义图像分割的空洞卷积DeepLabv3

一、什么是DeepLabv3&#xff1f; DeepLabv3 是用于语义分割任务的深度神经网络 (DNN) 架构。虽然不是比较新的网络模型&#xff0c;但是也是分割模型里的杰出代表之一&#xff0c;所以还是值得深入了解。 它使用Atrous&#xff08;Dilated&#xff09;卷积来控制感受野和特征图…

房贷计算器,妥妥的数学计算

根据给出的公式&#xff0c;编写房贷计算器。妥妥的数学计算&#xff0c;把数学公式“翻译”成代码就好。 (笔记模板由python脚本于2024年01月06日 18:08:55创建&#xff0c;本篇笔记适合初具基本编程能力的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;http…

服务器GPU温度过高挂掉排查记录

服务器GPU挂掉 跑深度学习的代码的时候发现中断了。通过命令查看&#xff1a; nvidia-smi显示 Unable to determine the device handle for GPU 0000:01:00.0: Unknown Error。感觉很莫名其妙。通过重启大法之后&#xff0c;又能用一段时间。 shutdown -r now但是过了一个小…

遗传算法(GA)、模拟退火算法(SAA)、蚁群算法(ACO)、粒子群算法(PSO)优缺点汇总

遗传算法 优点&#xff1a; 与问题领域无关且快速随机的搜索能力&#xff0c;不会陷入局部最优解&#xff1b;搜索从群体出发&#xff0c;具有潜在的并行性&#xff0c;提高运行速度&#xff0c;鲁棒性高&#xff1b;搜索使用评价函数启发&#xff0c;过程简单&#xff1b;使…

基于Java实现全功能电子商城

&#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩项目推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 基于SpringBoot的旅游网站 基于SpringBoot的MusiQ音乐网站 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及…

小游戏实战丨基于PyGame的俄罗斯方块小游戏

文章目录 写在前面PyGame五子棋注意事项系列文章写在后面 写在前面 本期内容&#xff1a;基于pygame的俄罗斯方块小游戏 下载地址&#xff1a;https://download.csdn.net/download/m0_68111267/88700182 实验环境 python3.11及以上pycharmtkinter PyGame Pygame是一个非常…

Java设计模式-模板方法模式

目录 一、豆浆制作问题 二、模板方法模式基本介绍 三、原理类图 四、模板方法模式解决豆浆制作问题 五、模板方法模式的钩子方法 六、模板方法模式在Spring框架应用的源码分析 七、注意事项和细节 一、豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下 : 1) 制作…

案例098:基于微信小程序的电子购物系统的设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【大数据进阶第三阶段之Datax学习笔记】使用阿里云开源离线同步工具DataX 实现数据同步

【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax概述 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax快速入门 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax类图 【大数据进阶第三阶段之Datax学习笔记】使用…

RH850P1X芯片学习笔记-A/D Converter (ADCF)

文章目录 Features of RH850/P1x-C ADCFNumber of UnitsRegister Base AddressClock SupplyInterrupts and DMAHardware ResetExternal Input/Output SignalsVirtual Channel OverviewFunctional OverviewBlock DiagramPhysical Channels, Virtual Channels and Scan Groups Re…