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

news2024/11/18 11:23:23

前言

在前一篇使用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格式给前端,前端解析返回的验证码以及其他用户信息可以进行验证码的读取,然后用户收到邮箱发来的验证码可以进行登录,进行用户输入的验证码和浏览器缓存的验证码进行比对然后登录成功。
还可以添加进行验证码的过期策略以及添加多种验证登录。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

性能分析与调优: Linux 性能分析60秒

目录 一、实验 1.环境 2.Linux性能分析60秒 一、实验 1.环境 &#xff08;1&#xff09;主机 表1-1 主机 主机架构组件IP备注prometheus 监测 系统 prometheus、node_exporter 192.168.204.18grafana监测GUIgrafana192.168.204.19agent 监测 主机 node_exporter192.168…

muduo网络库剖析——日志Log类

muduo网络库剖析——日志Log类 前情从muduo到my_muduo 概要日志日志级别 框架与细节成员函数 源码 前情 从muduo到my_muduo 作为一个宏大的、功能健全的muduo库&#xff0c;考虑的肯定是众多情况是否可以高效满足&#xff1b;而作为学习者&#xff0c;我们需要抽取其中的精华…

freesurfer-reconall后批量提取TIV(颅内总体积)

#提取TIV #singleline=$(grep Estimated Total Intracranial Volume /usr/local/freesurfer/subjects/bect-3d+bold-wangjingchen-4.9y-2/stats/aseg.sta

开启Android学习之旅-4-Android集成FontAwesome

FontAwesome 是一个非常标准、统一风格的图标库。产品经理在原型中应用了很多图标都是FontAwesome。正常流程是 UI 需要再手工绘制或在 iconfont 或 iconpark 网站挨个找&#xff0c;如果在 Android 直接使用不是省了一步&#xff08;注意版权问题&#xff0c;使用免费版&#…

贯穿设计模式-责任链模式

样例代码 涉及到的项目样例代码均可以从https://github.com/WeiXiao-Hyy/Design-Patterns.git获取 需求 实时地&#xff0c;根据city&#xff0c;sex&#xff0c;product字段进行业务投放&#xff0c;比如&#xff1a;北京的男生&#xff1b;四川的电脑等等 → 责任链模式&…

dyld: Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib

更新Xcode14后低版本iPhone调试报错 dyld: Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib Referenced from: /var/containers/Bundle/Application/…/….app/… Reason: image not found 这是缺少libswiftCoreGraphics库 直接导入libswiftCoreGraphics库即…

国产手机的遮羞布又被撕,市占率仅3%,苹果才是真第一!

国产手机纷纷宣称自己击败了苹果&#xff0c;不过这些第一全部加了定语&#xff0c;例如某周销量&#xff0c;某个价格段等等&#xff0c;而日前一加中国区总裁李杰则揭开了这层遮羞布&#xff0c;就全年来看苹果才是中国手机市场第一名&#xff01; 李杰指出市调机构BCI给出的…

华为云服务器试用领取

系列文章目录 华为云服务器试用领取 领取的试用云服务器在哪 文章目录 系列文章目录介绍 介绍 我将会用该系列文章讲述如何在云服务器中安装大数据软件及其环境搭建。如有不足之处&#xff0c;还望指点。 本篇文章讲述的是华为云服务器的免费试用。 华为弹性云服务器 ECS 该云…

基于 IP 多播的网络会议程序(2024)

1.题目描述 局域网 IP 多播程序&#xff0c;设计一个图形界面的网络会议程序&#xff08;实现文本多播方式即可&#xff09;。 2.演示Demo 3.参考代码 广播发送代码 //服务端 #include <winsock2.h> #include <iostream> #include <list>#pragma comment(l…

滑动窗口协议仿真(2024)

1.题目描述 滑动窗口协议以基于分组的数据传输协议为特征&#xff0c;该协议适用于在数据链路层以及传输层中对按 顺序传送分组的可靠性要求较高的环境。在长管道传输过程&#xff08;特别是无线环境&#xff09;中&#xff0c;相应的滑动窗口 协议可实现高效的重传恢复。附录 …

Guava Cache 异步刷新技巧

前言 Guava Cache是一款非常优秀的本地缓存框架&#xff0c;提供简洁易用的 API 供开发者使用。 这篇文章&#xff0c;我们聊聊如何使用 Guava Cache 异步刷新技巧带飞系统性能 。 1 基本用法 首先&#xff0c;在 Java 应用中添加 maven 依赖&#xff1a; <dependency&g…

jsES6+新语法

目录 模板字符串标签模板字符串 函数增强默认值与解构剩余参数rest和arguments 箭头函数 展开语法SymbolSetSet方法weakSetweakSet常用方法 MapMap常用方法weakMapweakMap常用方法 PromiseProxy/Reflect迭代器与生成器ES6新增方法includes**Object.valuesObject.entriespadStar…

【SpringBoot】公共字段自动填充功能实现(枚举、自定义注解、AOP、反射)

1. 自定义注解 使用interface语法来定义注解&#xff08;Annotation&#xff09;。 注解的参数类似无参数方法&#xff0c;可以用default设定一个默认值&#xff0c;比如String value() default "";。 元注解&#xff1a;有一些注解可以修饰其他注解&#xff0c;这…

Diffusion扩散模型学习2:DDPM前向加噪过程torch实现

参考: https://arxiv.org/pdf/2006.11239.pdf ##论文 https://github.com/dtransposed/code_videos/blob/main/01_Diffusion_Models_Tutorial/Diffusion%20Model.ipynb ##code https://spaces.ac.cn/archives/9119 1、红色框: 前向过程论文公式推出可以从x0原图一步到最终噪声…

学习Redis缓存

学习Redis缓存 NoSQL和SQL的区别缓存缓存作用缓存成本添加Redis缓存 Redis特征Redis中数据结构Redis通用命令String类型Key的层级格式Hash类型Redis的Java客户端 NoSQL和SQL的区别 缓存 缓存就是数据交换的缓冲区&#xff0c;是存储数据的临时地方&#xff0c;一般读写性比较高…

数据分析——火车信息

任务目标 任务 1、整理火车发车信息数据&#xff0c;结果的表格形式为&#xff1a; 2、并输出最终的发车信息表 难点 1、多文件 一个文件夹&#xff0c;多个月的发车信息&#xff0c;一个excel&#xff0c;放一天的发车情况 2、数据表的格式特殊 如何分析表是一个难点 数…

洛谷 P1019 单词接龙

题目背景 注意&#xff1a;本题为上古 NOIP 原题&#xff0c;不保证存在靠谱的做法能通过该数据范围下的所有数据。 NOIP2000 提高组 T3 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏&#xff0c;现在我们已知一组单词&#xff0c;且给定一个开头的字母&…

mysql视图和sql语句

mysql视图和sql语句 一.mysql视图1.数据的虚拟表示&#xff1a;2.简化复杂查询&#xff1a;3.安全性和权限控制&#xff1a;4.逻辑数据组织&#xff1a;5.更新限制&#xff1a;6.视图的创建&#xff1a; 二.mysq语句使用案列 MySQL的视图&#xff08;View&#xff09;是一个虚拟…

深入剖析pcap中的网络异常:TTL过期攻击、ARP中毒、TCP重传与重叠碎片等

网络流量数据包捕获是网络安全领域的重要部分&#xff0c;而pcap文件则是这一过程的常见载体。为了深入解析pcap文件中潜在的可疑网络流量&#xff0c;我们需要运用强大的网络安全威胁评估与审计工具。这些工具能够帮助我们捕捉、记录、检测和诊断网络中的数据传输问题&#xf…

c#调试程序一次启动两个工程(多个工程)

概述 c# - Visual Studio : debug multiple projects at the same time? 以在解决方案中设置多个启动项目(右键单击解决方案&#xff0c;转到设置启动项目&#xff0c;选择多个启动项目)&#xff0c;并为包含在解决方案(无、开始、不调试就开始)。如果您将多个项目设置为开始…