SpringBoot+阿里云实现验证码登录注册及重置密码

开通阿里云短信服务

阿里云官网
在这里插入图片描述

创建API的Key

在这里插入图片描述

可以使用手机号或者刷脸来进行创建Key

在这里插入图片描述

创建成功

在这里插入图片描述

开通完成以后接下来实现代码请求阶段

配置maven依赖

 <!-- 阿里云 oss 短信 依赖--><dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifactId><version>2.0.24</version></dependency>

在配置类中新建一个AccessKey类

package com.example.erp_project.config;/*** @author Lolo don‘t feel* @create 2022-05-09 16:09* 阿里云短信服务*/
public class AccessKey {// 阿里云短信服务// accessKeyIdpublic static final String accessKeyId = "你自己的accessKeyId";// accessKeySecretpublic static final String accessKeySecret = "你自己的accessKeySecret";// 短信模板code 对应下图的,你自己的code即可//账户注册public static final String templateCode = "你自己创建的模板的code";//密码重置public static final String templateCode2 = "你自己创建的模板的code";
}

在这里插入图片描述

创建短信发送服务类(在工具类中创建)

package com.example.erp_project.util;import com.aliyun.tea.TeaException;
import com.example.erp_project.config.AccessKey;/*** @author Lolo don‘t feel* 短信验证码*/
public class Sample {/*** 创建一个阿里云短信客户端的方法* 使用AK&SK初始化账号Client** @param accessKeyId* @param accessKeySecret* @return Client* @throws Exception*/public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {// 创建一个配置对象,用于存储AccessKey ID和AccessKey Secretcom.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()// 必填,您的 AccessKey ID.setAccessKeyId(accessKeyId)// 必填,您的 AccessKey Secret.setAccessKeySecret(accessKeySecret);// 设置请求的域名config.endpoint = "dysmsapi.aliyuncs.com";// 使用配置对象创建一个新的阿里云短信客户端并返回return new com.aliyun.dysmsapi20170525.Client(config);}/*** 发送验证码** @param phone            电话* @param verificationCode 验证码*/// 定义一个发送短信验证码的方法,参数为手机号、验证码和类型/*我这里设置的参数是三个参数,因为我定义了一个status来辨别发送的短信模板,*正常情况下是手机号和验证码两个参数,如果你的模板不一样也可以使用一个参数来辨别		该使用哪个模板*/public static void sendingCode(String phone, String verificationCode, Integer status) {// 创建一个阿里云短信客户端对象com.aliyun.dysmsapi20170525.Client client = null;try {// 使用AccessKeyId和AccessKeySecret创建客户端//引用上方createClient方法创建客户端client = Sample.createClient(AccessKey.accessKeyId, AccessKey.accessKeySecret);} catch (Exception e) {e.printStackTrace();}// 创建一个发送短信请求对象,并设置签名、手机号和模板参数com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()// 设置签名名称.setSignName("暖意ERP")// 设置手机号.setPhoneNumbers(phone)// 设置模板参数验证码.setTemplateParam("{\"code\":\"" + verificationCode + "\"}");//注:如果你只设置了一个通用模板你就把sendSmsRequest.setTemplateCode(AccessKey.templateCode);从if中拿出来就可以了// 根据类型设置不同的模板代码if (status == 1) {//如果类型为1,则使用模板代码1注册模板sendSmsRequest.setTemplateCode(AccessKey.templateCode);} else if (status == 2) {//如果类型为2,则使用模板代码2重置密码模板sendSmsRequest.setTemplateCode(AccessKey.templateCode2);}// 创建一个运行时选项对象com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();try {// 使用客户端发送短信请求client.sendSmsWithOptions(sendSmsRequest, runtime);} catch (TeaException error) {// 处理TeaException异常com.aliyun.teautil.Common.assertAsString(error.message);} catch (Exception _error) {// 处理其他异常TeaException error = new TeaException(_error.getMessage(), _error);com.aliyun.teautil.Common.assertAsString(error.message);}}}

接下来就是在短信验证的时候进行验证了(loginController)

这里是账户注册的时候进行短信验证,我将结果保存到了session中用于账户提交注册的时候进行验证

 /** 验证码获取,用于账户注册及账户密码重置* sendValidateCode* */@GetMapping("/sendValidateCode")public ResultUtil sendValidateCode(@RequestParam(value = "phone") String phone,@RequestParam(value = "status") Integer status, HttpSession session) {//测试手机号和验证码类型是否正确// System.out.println("手机号:"+phone);// System.out.println("验证码类型:"+status);// 判断手机号和验证码类型是否为空if (phone != null && status != null) {// 验证码String verificationCode = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));// System.out.println("验证码:"+verificationCode);//验证码发送,调用短信发送工具类Sample.sendingCode(phone, verificationCode, status);// 将验证码和当前手机号存入session,在账户注册的时候进行校验操作session.setAttribute("phone", phone);//保存当前发送时间session.setAttribute("sendTime", new Date());//将状态存入sessionsession.setAttribute("status", status);// 将验证码存入sessionsession.setAttribute("verificationCode", verificationCode);// 返回成功信息return ResultUtil.ok(0, "验证码发送成功,请注意查收哦!");}// 返回失败信息return ResultUtil.error("验证码发送失败");}

获取验证码对应的js部分代码

<!--引用第三方插件(消息通知插件)-->
<script th:src="@{/dist/notify/notify.js}"></script>
<script>layui.use(['notify'], function () {var $ = layui.$;var form = layui.form;var layer = layui.layer;var util = layui.util;var notify = layui.notify;// 获取验证码进行验证$('#validate-get-vercode').on('click', function () {var isValid = form.validate('#reg-cellphone');  // 验证手机号进行主动触发//获取手机号var cellphone = $('#reg-cellphone').val();//console.log("注册手机号:"+cellphone);// 验证通过if (isValid) {//向后端发送验证码请求$.ajax({type: 'GET',url: "/auth/sendValidateCode",//实现验证data: {"phone": cellphone, "status": 1},success: function (d) { // 返回的RequestResult的json对象if (d.code === 0) {notify.info(d.msg, "vcenter", "shadow", false);/** 实现获取验证码按钮倒计时的代码*///禁用按钮不可再次点击,这里如果不设置就会一直点击倒计时会重复计时document.getElementById('validate-get-vercode').disabled = true;// 倒计时60s以后可再次点击var count = 60;//定义时间var countdown = setInterval(function () {if (count > 0) {//按钮文字倒计时信息提示document.getElementById('validate-get-vercode').innerText = count + 's后再次获取';//时间减count--;} else {//倒计时结束以后按钮文字提示显示document.getElementById('validate-get-vercode').innerText = '获取验证码';//取消按钮禁用,用于验证码过期以后进行再次获取document.getElementById('validate-get-vercode').disabled = false;clearInterval(countdown);}},1000);//按钮倒计时结束} else {notify.error(d.msg, "vcenter", "shadow", false);}},})}});});
</script>

在这里插入图片描述

下面就是点击注册账户按钮实现账户注册操作的代码

js部分
<!--引用第三方插件(消息通知插件)-->
<script th:src="@{/dist/notify/notify.js}"></script>
<script>layui.use(['notify'], function () {var $ = layui.$;var form = layui.form;var layer = layui.layer;var util = layui.util;var notify = layui.notify;// 验证注册密码是否一致form.verify({// 确认密码confirmPassword: function (value, item) {var passwordValue = $('#password').val();if (value !== passwordValue) {return '两次密码输入不一致';}}});// 提交账户注册事件form.on('submit(register)', function (data) {var field = data.field; // 获取表单字段值//验证码为6位if (!/^\d{6}$/.test(field.vercode)) {notify.warning('验证码必须为 6 位的数字', "vcenter", "shadow", false);return false;}//验证密码if (!/^[\S]{6,16}$/.test(field.password)) {notify.warning('密码必须为 6 到 16 位的非空字符', "vcenter", "shadow", false);return false;}// 是否勾选同意if (!field.agreement) {notify.info('您必须勾选同意服务条款才能注册账户', "vcenter", "shadow", false);return false;}// 获取表单信息将账户及密码传递到后断进行验证notify.loading("系统正在验证并注册新账户,请稍等", "vcenter", "shadow", false);setTimeout(function () {notify.destroyAll(); //先关闭loading$.ajax({type: 'POST',url: "/auth/register",//实现账户注册请求data: {"account": field.cellphone,   // 手机号"vercode": field.vercode, // 验证码"password": field.password, // 密码"nickname": field.nickname // 昵称},success: function (d) { // 返回的RequestResult的json对象if (d.code === 0) {//账户注册成功notify.success(d.msg, "vcenter", "shadow", false)} else if (d.code === 1) {//账户存在,或者验证码错误提示notify.warning(d.msg, "vcenter", "shadow", false);} else {//账户注册失败notify.error(d.msg, "vcenter", "shadow", false);}},}).done(function () {setTimeout(function () {parent.location.reload();//重载页面}, 1500);});}, 3000);return false; // 阻止默认 form 跳转});});
</script>

接着再是controller代码

    /** 账户注册* register* */@PostMapping("/register")public ResultUtil register(@RequestParam(value = "account") String account,@RequestParam(value = "password") String password,@RequestParam(value = "vercode") String vercode,@RequestParam(value = "nickname") String nickname,HttpSession session) {//测试数据//System.out.println("账户:"+account+"密码:"+password+"验证码:"+vercode+"昵称:"+nickname);//从session中获取验证码String verificationCode = (String) session.getAttribute("verificationCode");//从session中获取手机号String phone = (String) session.getAttribute("phone");//获取session中的发送时间Date sendTime = (Date) session.getAttribute("sendTime");//从session中获取验证码类型Integer status = (Integer) session.getAttribute("status");//第一步判断,这里必须要status为1,否则就是验证码类型错误if (status != null && status == 1) {//如果session中没有发送时间,则验证码失效,这里如果不做判断会报错导致下面时间判断出错if (sendTime==null){return ResultUtil.warning(1,"验证码已失效,请重新获取验证码");}//判断如果现在时间大于发送时间5分钟,则验证码失效if (new Date().getTime() - sendTime.getTime() > 5 * 60 * 1000) {//清空session中的手机号session.removeAttribute("phone");//清空session中的验证码session.removeAttribute("verificationCode");//清空session中的发送时间session.removeAttribute("sendTime");//验证码失效return ResultUtil.warning(1, "验证码已失效,请重新获取验证码");}//判断当前的手机号和验证码是否与session中的手机号和验证码是否一致if (phone.equals(account) && verificationCode.equals(vercode)) {//根据账户查询用户信息,如果用户信息为空,则进行注册操作UserEntity user = userService.getUserByAccount(account);if (user == null) {// 密码加密String encrypt = MD5Util.encrypt(password);// 创建用户实体UserEntity userEntity = new UserEntity();// 设置用户信息userEntity.setAccount(account);// 设置密码userEntity.setPassword(encrypt);//设置昵称userEntity.setNickname(nickname);//设置状态userEntity.setStatus(1);//设置角色userEntity.setRoleId(2);//进行注册userService.registerAccount(userEntity);//返回成功信息return ResultUtil.ok(0, "账户注册成功!");}return ResultUtil.warning(1,"该账户已存在,请勿重复注册");}return ResultUtil.warning(1, "请输入正确的手机号或验证码");}return ResultUtil.error( "该验证码不适用于当前操作!");}
ok以上就是SpringBoot结合阿里云实现短信验证码的完整代码,也不能说这篇文章很详细吧,自我感觉能够帮助有需要的伙伴,如果觉得改文章对你有用,可以评论一波哈,当然如果有不足之处,恳请各位在评论区指正,这样更方便他人能够发现并及时更改。上面我用的是注册账户的方法,登录或者密码找回实现的思路基本上是一样的,所以这里就没有呈现了。

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

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

相关文章

三、VUE数据代理

一、初识VUE 二、再识VUE-MVVM 三、VUE数据代理 Object.defineProperty() Object.defineProperty() 静态方法会直接在一个对象上定义一个新属性&#xff0c;或修改其现有属性&#xff0c;并返回此对象。 Object.defineProperty() 数据代理 通过一个对象代理另一个对象中属…

【imazing骗局】imazing软件安全吗 需要越狱吗 为什么iPhone都会装iMazing来管理

鉴于苹果设备的封闭性与安全性&#xff0c;我们大部分情况下都需要搭配iTunes进行设备的管理。但作为一款全方位的iOS设备管理软件&#xff0c;iMazing竟然可以突破iTunes的限制&#xff0c;与设备直接连接&#xff0c;进行备份、管理等操作。 因此&#xff0c;很多人都会有疑…

太速科技-基于6U CPCIe的TMS320C6678+KU060的信号处理板卡

基于6U CPCIe的TMS320C6678KU060的信号处理板卡 一、板卡概述 基于6U CPCIe的C6678KU060的信号处理板卡是新一代FPGA的高性能处理板卡。板卡采用一片TI DSP TMS320C6678和一片Xilinx公司 XCKU060-2FFVA1156I作为主处理器&#xff0c;Xilinx 的Aritex XC7A200T作为辅助处…

数据结构——栈的应用

数据结构——栈的应用 括号匹配中缀转后缀什么是中缀后缀中缀表达式 (Infix Notation)后缀表达式 (Postfix Notation, Reverse Polish Notation, RPN) 加减&#xff0c;乘除运算处理括号后缀转中缀 我们今天来看栈的应用&#xff1a; 括号匹配 栈一个经典的应用就是括号匹配&…

set_input_delay的理解

1&#xff0c;set_input_delay约束理解 input_delay是指输入的数据到达FPGA的pad引脚时相对于时钟边沿的延迟有多大&#xff0c;单位是ns&#xff0c;数值可以是正&#xff0c;也可以是负。通过set_input_delay约束告诉编译器输入时钟和输入数据的相位关系。如下图所示假设时钟…

数字IC后端先进工艺设计实现之TSMC 12nm 6Track工艺数字IC后端实现重点难点盘点

大家知道咱们社区近期TSMC 12nm ARM Cortexa-A72(1P9M 6Track Metal Stack)已经开班。这里小编要强调一点:不要认为跑了先进工艺的项目就会很有竞争力&#xff01;如果你仅仅是跑个先进工艺的flow&#xff0c;不懂先进工艺在数字IC后端实现上的不同点&#xff0c;为何有这样的不…

推荐一个wordpress免费模板下载

首页大背景图&#xff0c;首屏2张轮播图&#xff0c;轮换展示&#xff0c;效果非常的炫酷&#xff0c;非常的哇噻&#xff0c;使用这个主题搭建的wordpress网站&#xff0c;超过了200个&#xff0c;虽然是一个老主题了&#xff0c;不过是经得起时间考验的&#xff0c;现在用起来…

[iOS]使用CocoaPods发布公开库

1.检查库名是否已被占用 选择库名时&#xff0c;尽量选择具有描述性并且独特的名字&#xff0c;这不仅可以避免命名冲突&#xff0c;还可以帮助用户更好地理解库的用途和功能。 在实际创建和发布 CocoaPods 库之前&#xff0c;确实应该检查库名是否已经被占用&#xff0c;以避…

敏捷之Scrum开发

目录 一、什么是 Scrum 1.1 Scrum 的定义 二、Scrum 迭代开发过程 2.1 迭代开发过程说明 2.1.1 开发方法 2.1.1.1 增量模型 2.1.1.1.1 定义 2.1.1.1.2 模型方法说明 2.1.1.2 迭代模型 2.1.1.2.1 定义 2.1.1.2.2 模型方法说明 2.1.2 迭代过程 2.1.2.1 产品需求Produ…

万万没想到,原来这些维生素对帕金森有好处!

亲爱的读者朋友们&#xff0c;今天我们要聊一个特别的群体——帕金森病患者。在面对这一神经系统退行性疾病时&#xff0c;除了遵循医嘱进行药物治疗和康复锻炼&#xff0c;合理的饮食和营养补充也显得尤为重要。那么&#xff0c;究竟哪些维生素是他们不可或缺的呢&#xff1f;…

go语言实现简单登陆返回token样例

目录 1、代码实现样例&#xff1a; 2、postman调用&#xff0c;获取登陆后的token&#xff1a; 1、代码实现样例&#xff1a; package mainimport ("net/http""time""github.com/dgrijalva/jwt-go""github.com/gin-gonic/gin" )var …

【代码问题】【Pytorch】训练模型时Loss为NaN或INF

解决方法或者问题排查&#xff1a; 加归一化层&#xff1a; 我的问题是我新增的一个模块与原来的模块得到的张量相加&#xff0c;原张量是归一化后的&#xff0c;我的没有&#xff1a; class Module(nn.Module):def __init__(self,dim,):super().__init__()# 新增一个LayerNo…

python学习笔记B-13:序列结构之元组--元组的相关操作

元组的常用相关操作有&#xff1a;获取最大值、获取最小值、获取元组长度、查询是否包好某元素、获取元素索引值、获取元素数量 t (2,4,6,90,34,25,78) print("原元组&#xff1a;",t) print("最大值&#xff1a;",max(t)) print("最小值&#xff1…

matlab新手快速上手3(差分进化算法)

本文用经典差分进化框架模板&#xff0c;对matlab新手友好&#xff0c;快速上手看懂matlab代码&#xff0c;快速应用实践&#xff0c;源代码在文末给出。 差分进化算法定义&#xff1a; 差分进化算法&#xff08;Differential Evolution&#xff0c;简称DE算法&#xff09;是…

KUKA机器人如何给IO信号或寄存器添加中文注释信息?

KUKA机器人如何给IO信号或寄存器添加中文注释信息? 如下图所示,首先,我们需要登录专家以上用户权限(默认密码KUKA), 如下图所示,点击“投入运行”—“网络配置”, 如下图所示,此时机器人的IP地址为192.168.1.10, 如下图所示,用一根网线连接机器人控制柜到笔记…

基于SpringBoot+Vue大学生兼职管理系统的设计与实现

目录 一、前言介绍 二、功能需求 三、功能结构设计 四、管理员功能实现 招聘单位管理 用户管理 论坛管理 公告信息管理 五、招聘单位功能实现 职位招聘管理 职位留言管理 简历投递管理 六、用户功能实现 在线论坛 职位招聘信息 简历投递 简历 七、部分核心代码 …

【C语言进阶】程序编译中的预处理操作

&#x1f4da;作者简介&#xff1a;爱编程的小马&#xff0c;正在学习C/C&#xff0c;Linux及MySQL.. &#x1f4da;以后会将数据结构收录为一个系列&#xff0c;敬请期待 ● 本期内容讲解C语言中程序预处理要做的事情 目录 1.1 预处理符号 1.2 #define 1.2.1 #define定义标识…

数据结构---线性表(顺序表)附代码

目录&#xff1a; 数据结构相关概念 1、什么是数据结构&#xff1f; 2、为什么需要数据结构&#xff1f; 顺序表 1、顺序表的概念及结构 1.1 线性表 1.2 顺序表 2、顺序表分类 3、动态顺序表的实现 什么是数据结构&#xff1f;&#xff1f; 数据结构是由 “数据”和 …

Unity 合并子物体获得简化Mesh

合并子物体获得简化Mesh &#x1f959;环境&#x1f96a;Demo &#x1f959;环境 PackageManager安装Editor Coroutines 导入插件&#x1f448; &#x1f96a;Demo 生成参数微调&#xff1a;Assets/EasyColliderEditor/Scripts/VHACDSettings/VHACDSettings.asset

MATLAB数值类型

MATLAB 数值 MATLAB支持各种数字类&#xff0c;包括有符号和无符号整数以及单精度和双精度浮点数。默认情况下&#xff0c;MATLAB将所有数值存储为双精度浮点数。 您可以选择将任何数字或数字数组存储为整数或单精度数字。 所有数值类型都支持基本数组运算和数学运算。 转换…