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 {
    // 阿里云短信服务
    // accessKeyId
    public static final String accessKeyId = "你自己的accessKeyId";
    // accessKeySecret
    public 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 Secret
        com.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());
            //将状态存入session
            session.setAttribute("status", status);
            // 将验证码存入session
            session.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.mfbz.cn/a/590404.html

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

相关文章

Python的使用

1、打印&#xff1a;print&#xff08;‘hello’&#xff09; 2、Python的除法是数学意义上的除法 print&#xff08;2/3&#xff09; 输出&#xff1a;0.6666... 3、a18 a‘hello’ print(a) 可以直接输出 4、**2 表示2的平方 5、打印类型 print&#xff08;type&am…

【深度学习】第二门课 改善深层神经网络 Week 1 深度学习的实践层面

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;深度学习 &#x1f4ac;总结&#xff1a;希望你看完之后&#xff0c;能对…

R语言学习—6—多元相关与回归分析

1、引子 xc(171,175,159,155,152,158,154,164,168,166,159,164) #身高 yc(57,64,41,38,35,44,41,51,57,49,47,46) #体重 par(marc(5,4,2,1)) #设定图距离画布边缘的距离&#xff1a;下5&#xff0c;左4&#xff0c;上2&#xff0c;右1 plot(x,y) 2、相关…

【华为 ICT HCIA eNSP 习题汇总】——题目集20

1、&#xff08;多选&#xff09;若两个虚拟机能够互相ping通&#xff0c;则通讯过程中会使用&#xff08;&#xff09;。 A、虚拟网卡 B、物理网卡 C、物理交换机 D、分布式虚拟交换机 考点&#xff1a;数据通信 解析&#xff1a;&#xff08;AD&#xff09; 物理网卡是硬件设…

webpack 常用插件

clean-webpack-plugin 这个插件的主要作用是清除构建目录中的旧文件&#xff0c;以确保每次构建时都能得到一个干净的环境。 var { CleanWebpackPlugin } require("clean-webpack-plugin") const path require("path");module.exports {mode: "de…

docker 基础命令

docker 安装 更新系统 sudo apt update sudo apt -y dist-upgrade安装docker sudo apt-get -y install ca-certificates curl gnupg lsb-release sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/…

数据结构——链表(精简易懂版)

文章目录 链表概述链表的实现链表的节点&#xff08;单个积木&#xff09;链表的构建直接构建尾插法构建头插法构建 链表的插入 总结 链表概述 1&#xff0c;链表&#xff08;Linked List&#xff09;是一种常见的数据结构&#xff0c;用于存储一系列元素。它由一系列节点&…

双链表的应用

cf edu161 D. Berserk Monsters 思路&#xff1a; 因为考虑到&#xff0c;每个怪是否死亡与其左右的怪息息相关&#xff0c;再者&#xff0c;若当前怪死亡&#xff0c;周围怪的相邻信息也会产生变化&#xff0c;由此可以想到使用双链表进行维护&#xff0c;双链表的维护方式有…

STM32——中断篇

技术笔记&#xff01; 1 中断相关概念 1.1 什么是中断&#xff1f; 中断是单片机正在执行程序时&#xff0c;由于内部或外部事件的触发&#xff0c;打断当前程序&#xff0c;转而去处理这一事件&#xff0c;当处理完成后再回到原来被打断的地方继续执行原程序的过程。 在AR…

算法学习系列(五十四):单源最短路的综合应用

目录 引言一、新年好二、通信线路三、道路与航线四、最优贸易 引言 关于这个单源最短路的综合应用&#xff0c;其实最短路问题最简单的就是模板了&#xff0c;这是一个基础&#xff0c;然后会与各种算法结合到一块&#xff0c;就是不再考察单个知识点了&#xff0c;而是各种知…

ICode国际青少年编程竞赛- Python-1级训练场-基础训练1

ICode国际青少年编程竞赛- Python-1级训练场-基础训练1 1、 Dev.step(4)2、 Dev.step(-4) Dev.step(8)3、 Dev.turnLeft() Dev.step(4)4、 Dev.step(3) Dev.turnLeft() Dev.step(-1) Dev.step(4)5、 Dev.step(-1) Dev.step(3) Dev.step(-2) Dev.turnLeft() Dev.step(…

su03t语音模块烧录识别不出问题解决方法

今天被su03t模块的烧写问题&#xff0c;卡了一下午&#xff0c;也是非常困惑。所幸到现在已经能够解决问题&#xff0c;并且有一些心得&#xff0c;因此想要记录一下&#xff0c;也可以帮助有同样困惑的小伙伴。 首先我们来说一下接线问题&#xff0c;因为要利用到ch340&#x…

使用DataGrip连接DM达梦数据库

前言 达梦数据库虽然提供了官方的数据库管理工具"DM管理工具"&#xff0c;但是该软件经常莫名卡顿&#xff0c;影响开发效率和心情。所以&#xff0c;本人一般使用DataGrip进行数据库操作。DataGrip是JetBrains公司开发的一款强大的数据库IDE&#xff0c;支持多种数…

SpringBoot 打包所有依赖

SpringBoot 项目打包的时候可以通过插件 spring-boot-maven-plugin 来 repackage 项目&#xff0c;使得打的包中包含所有依赖&#xff0c;可以直接运行。例如&#xff1a; <plugins><plugin><groupId>org.springframework.boot</groupId><artifact…

Appium + mitmProxy 实现APP接口稳定性测试

随着 App 用户量的不断增长&#xff0c;任何小的问题都可能放大成严重的线上事故&#xff0c;为了避免对App造成损害的任何可能性&#xff0c;我们必须从各个方面去思考 App 的稳定性建设&#xff0c;尽可能减少任何潜在的威胁。 1.背景介绍 为了保障 App 的稳定性&#xff0c…

Linux的Shell脚本详解

本文目录 一、什么是 Shell 脚本文件 &#xff1f;二、编写Shell脚本1. 基本规则2. shell 变量&#xff08;1&#xff09;创建变量&#xff08;2&#xff09;引用变量&#xff08;3&#xff09;删除变量&#xff08;4&#xff09;从键盘读取变量&#xff08;5&#xff09;特殊变…

【USB 3.2 Type-C】 端口实施挑战的集成解决方案 (补充一)

USB 3.2 Type-C 端口集成 补充&#xff0c;上一篇感觉还有没理解到位的一部分&#xff1b; 一、只做正反插的通信&#xff0c;已经差不多够了&#xff0c;但是这并不是完整的TYPE-C,必须要补充上PD; 参考连接&#xff1a; TYPE-C PD浅谈&#xff08;一&#xff09;https://w…

【MyBatis】深入解析MyBatis:高效操作数据库技术详解

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【MyBatis】深入解析MyBatis&#xff1a;高效操作数据库技术详解 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 动态SQL1. \<if>标签2. \<trim&…

易查分查询分组功能如何使用?

期中考试马上要陆续开始&#xff0c;老师如果负责多个班级或年级&#xff0c;如何把同一级部的查询单独放到一个列表页呢&#xff1f; 易查分的查询分组功能就可实现&#xff0c;下面就来教大家如何使用此功能。 &#x1f4d6;案例&#xff1a;负责相关工作的老师&#xff0c;需…

(代码结构3)项目redis key 管理

场景:项目中到处可见的key&#xff0c;没有统一管理&#xff0c;极其难维护。大佬同事实现了一个。 代码 如图,Redis.php 是对redis的二次封装&#xff0c;对redis key模块的强制校验&#xff0c;FillerKeyTrait.php 是对filler模块的key获取。主要原理是:对redis二次封装&…