java发送QQ邮箱验证码实现登录注册、邮箱验证码防刷校验

news2024/11/19 3:32:20

文章目录

  • 一:前台功能实现
    • 1.1 页面编写
    • 1.2 发送验证码——sendEmailCode
      • 1.2.1 远程调用发送接口
      • 1.2.1 接口防刷校验——60s内只能发送一次
  • 二:获取QQ邮箱授权码
    • 2.1 登录QQ邮箱
    • 2.2 开启SMTP权限
      • 2.2.1 设置
      • 2.2.2 账户
      • 2.2.3 管理服务
      • 2.2.4 生成授权码
      • 2.2.5 复制授权码
  • 三:后台功能实现
    • 3.1 编写配置文件
    • 3.2 发送验证码工具类
    • 3.3 验证码防刷校验——60s内不允许再次发送
    • 3.4 通过验证码登录

一:前台功能实现

1.1 页面编写

在这里插入图片描述

<el-form id="emailForm" size="medium">
                        <el-row>
                            <el-col :span="24">
                                <el-form-item class="icon1" label="邮箱:" prop="email">
                                    <el-input placeholder="邮箱" id="email" style="width: 80%;" v-model="emailForm.email" type="text"></el-input>
                                </el-form-item>
                            </el-col>
                        </el-row>

                        <el-row>
                            <el-col :span="24">
                                <el-form-item class="icon1" label="验证码:" prop="checkCode">
                                    <el-input type="text" id="checkCode" v-model="emailForm.checkCode" style="width: 45%;" placeholder="验证码"></el-input>
                                    <a @click="sendEmailCode" id="sendEmailCode" >邮箱验证码</a>
                                </el-form-item>
                            </el-col>
                        </el-row>

                    </el-form>

1.2 发送验证码——sendEmailCode

1.2.1 远程调用发送接口

			/**
             * 发送邮箱验证码
             */
            sendEmailCode(){
                /**
                 * 1.给指定邮箱发送验证码
                 * 2.添加验证码倒计时功能
                 */
                //判断有没有正在进行倒计时操作
                if($(this).hasClass("disabled")){
                    //正在倒计时
                } else {
                    //给指定的手机发送验证码
                    let email = this.emailForm.email;
                    $.get("/sendEmail?email=" + email);
                    this.timeoutChangeStyleEmail();
                }
            },

1.2.1 接口防刷校验——60s内只能发送一次

			timeoutChangeStyleEmail(){
                $("#sendEmailCode").attr("class","disabled");
                if( this.num == 0){
                    $("#sendEmailCode").text("发送验证码");
                    this.num = 60;
                    $("#sendEmailCode").attr("class","");
                } else {
                    let str = this.num + "s 后再次发送";
                    $("#sendEmailCode").text(str);
                    setTimeout(() => {
                        this.timeoutChangeStyleEmail();
                    }, 1000);
                }
                this.num--;
            },

在这里插入图片描述

二:获取QQ邮箱授权码

2.1 登录QQ邮箱

https://wx.mail.qq.com/

2.2 开启SMTP权限

主页->设置->账户->管理服务

2.2.1 设置

在这里插入图片描述

2.2.2 账户

在这里插入图片描述

2.2.3 管理服务

在这里插入图片描述

2.2.4 生成授权码

在这里插入图片描述

2.2.5 复制授权码

![在这里插入图片描述](https://img-blog.csdnimg.cn/9d9fc7674c164692a5be79c9b7ee4c9d.png

三:后台功能实现

3.1 编写配置文件

spring:
  mail:
    host: smtp.qq.com   #给QQ邮箱发送邮件
    username: ##你的QQ邮箱
    password: ###你刚才复制的授权码##
    port: 465
    protocol: smtp
    default-encoding: utf-8
    properties:
      mail:
        # 开启 debug,这样方便开发者查看邮件发送日志
        debug: true
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
          ssl:
            enable: true
          socketFactory:
            port: 465
            class: javax.net.ssl.SSLSocketFactory

3.2 发送验证码工具类

package com.sysg.user.utils;

import com.sysg.base.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.Random;

/**
 * 发送邮件验证码
 */
@Component
@Slf4j
public class EmailUtil {

    @Autowired
    private JavaMailSender javaMailSender;

    /**
     * 读取yml文件中username的值并赋值给sendUserEmail
     */
    @Value("${spring.mail.username}")
    private String sendUserEmail;

    /**
     * 发送邮件验证码
     * @param emailReceiver
     * @return
     */
    public String sendSimpleMail(String emailReceiver) {
        // 构建一个邮件对象
        SimpleMailMessage message = new SimpleMailMessage();
        // 设置邮件发送者
        message.setFrom(sendUserEmail);
        // 设置邮件接收者
        message.setTo(emailReceiver);
        // 设置邮件的主题
        message.setSubject("登录验证码");
        // 设置邮件的正文
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int r = random.nextInt(10);
            code.append(r);
        }
        String text = "您的验证码为:" + code + ",请勿泄露给他人。";
        message.setText(text);
        // 发送邮件
        try {
            javaMailSender.send(message);
            log.info("邮件发送成功");
            return code.toString();
        } catch (MailException e) {
            e.printStackTrace();
            log.info("邮件发送失败");
            return StringUtils.EMPTY;
        }
    }
}

此时就收到验证码了
在这里插入图片描述

3.3 验证码防刷校验——60s内不允许再次发送

	public R sendEmail(String email) {
        try {
            //1.接口防刷,防止同一个手机号60s内再次发送
            //UserConstant.EMAIL_CODE_CACHE_PREFIX自行去定义
            String redisEmailCode = stringRedisTemplate.opsForValue().get(UserConstant.EMAIL_CODE_CACHE_PREFIX + email);
            if(!StringUtils.isEmpty(redisEmailCode)){
                long redisDate = Long.parseLong(redisEmailCode.split("_")[1]);
                if(System.currentTimeMillis() - redisDate < 60000){
                    //60秒内不可以再发
                    return R.error("获取验证码过于频繁,请您稍后再试");
                }
            }
            String emailCode = emailUtil.sendSimpleMail(email);
            String dateEmailCode = emailCode + "_" + System.currentTimeMillis();
            //2.验证码的再次校验,存储到redis中。key-email,value-code
            //key——"code:15648961564"  value-564986
            //保存到redis里面,并设置10分钟超时时间
            stringRedisTemplate.opsForValue().set(UserConstant.EMAIL_CODE_CACHE_PREFIX + email,dateEmailCode,10, TimeUnit.MINUTES);
            return R.ok("验证码发送成功");
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return R.error("验证码发送失败");
        }
    }

3.4 通过验证码登录

public R emailLogin(EmailLoginVo vo, HttpSession session) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("email",vo.getEmail());
        User user = userDao.selectOne(wrapper);
        if( user == null){
            return R.error(500, "当前邮箱没有注册,请注册后在使用");
        }
        String token = null;
        //1.校验验证码
        String code = vo.getCheckCode();
        String s = stringRedisTemplate.opsForValue().get(UserConstant.EMAIL_CODE_CACHE_PREFIX + vo.getEmail());
        if(!StringUtils.isEmpty(s)){
            if(code.equals(s.split("_")[0])){
                //校验完成以后删除验证码
                stringRedisTemplate.delete(UserConstant.EMAIL_CODE_CACHE_PREFIX + vo.getEmail());
                //验证码校验通过,登录成功
                String username = user.getUsername();
                //生成token
                token = JwtUtil.createToken(username);
                if(token != null){
                    //将数据存储到session对象中
                    session.setAttribute("user",username);
                    return R.ok(200, "登录成功",token);
                }else{
                    return R.error(400, "登录失败");
                }

            } else {
                return R.error("验证码错误");
            }
        } else {
            //验证码不存在的话,就说明过期了
            return R.error("验证码错误");
        }
    }

此时功能就实现了!!!

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

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

相关文章

新能源商用车:老玩家、新势力“争先恐后”

现如今&#xff0c;作为重要出行交通工具之一的汽车&#xff0c;已经在人们日常生活中扮演着愈发重要的角色。不仅如此&#xff0c;汽车行业也发生了不小的变化&#xff0c;新能源汽车的热度更是居高不下。除了各路玩家积极布局之外&#xff0c;新能源汽车的销量也是持续走高。…

python---列表和元组(1)

变量就是内存空间,用来表示/存储数据. 如果表示的数据少,直接定义几个变量就行了. 但是有的时候表示的数据比较多,就很麻烦 在python中就有列表和元组,就是这样的机制,可以用一个变量表示很多的数据. 这就类比于其他编程语言中的"数组" 列表和元组大部分的功能是差…

智安网络|深谈网络安全难点的根源和解决之道

随着数字化和网络化的加速发展&#xff0c;人们面临的网络安全问题日益增多。由于网络安全威胁的多样性和复杂性&#xff0c;网络安全防护变得越来越困难。本文将从几个方面来探讨网络安全难点的根源和解决之道。 一. 网络安全威胁的复杂性 网络安全威胁种类繁多&#xff0c;主…

Junit执行器Runner探索之旅 | 京东云技术团队

单元测试是每个程序员必备的技能&#xff0c;而Runner是每个单元测试类必有属性。本文通过解读Junit源码&#xff0c;介绍junit中每个执行器的使用方法&#xff0c;让读者在单元测试时&#xff0c;可以灵活的使用Runner执行器。 一、背景 在今年的敏捷团队建设中&#xff0c;…

07 lvgl-边框样式

void lv_100ask_demo_course_2_1_1(void){ static lv_style_t style;lv_style_init(&style);/*Set a background color and a radius*/lv_style_set_radius(&style, 5); //半径lv_style_set_bg_opa(&style, LV_OPA_COVER); //透明度lv_style_set_bg_color(&st…

xlsx是什么格式的文件?xlsx文件删除了怎么恢复

如果您在工作中不小心删除了重要的xlsx文件怎么办&#xff1f;xlsx文件删除了怎么恢复&#xff1f;本文将介绍如何在不同情况下恢复xlsx文件的实用技巧&#xff0c;帮助您有效的找回文件。 第一部分&#xff1a;xlsx是什么格式的文件 XLSX是一种电子表格文件格式&#xff0c;…

JAVA 实现 Redis 发布订阅

Redis 发布订阅 发布订阅&#xff1a;消息发布者发布消息 和 消息订阅者接收消息&#xff0c;两者之间通过某种媒介联系起来 例如订杂志&#xff0c;当自己订阅了爱格杂志&#xff0c;每个月会发刊一本。到发布的时候派送员将杂志送到自己手上就能看到杂志内容。只有我们订阅了…

为什么美颜插件比传统集成方式更快?

都说云市场插件快&#xff0c;快在哪里呢&#xff1f; 美颜功能是实时互动应用的基础功能&#xff0c;广泛应用在社交、直播、约会、会议等场景&#xff0c;开发者们往往在集成美颜功能时候非常头疼。今天&#xff0c;我们来介绍云市场美颜插件相比传统的裸数据集成方式快在哪…

Unity与原生交互之Unity篇——AndroidStudio导出aar/jar包供Unity使用实现交互全流程(2)

序言:此篇介绍在(1)的基础上引入Unity的API库进行交互,原生调Unity 1.导入Unity库 注意: (1)老版本Unity的classes.jar里包含UnityPlayerActivity API (2)新版本Unity的UnityPlayerActivity API 在UnityEditor安装路径中,需单独导入,后续介绍 1.1导入unity的classes.jar …

Seesion会话超时时间测试-业务安全测试实操(3)

Seesion会话超时时间测试, Cookie仿冒测试, 密文比对认证测试 本地加密传输测试-业务安全测试实操(2)_luozhonghua2000的博客-CSDN博客 测试原理和方法 在用户成功登录系统获得Session认证会话后,该Session认证会话应具有生命周期,即用户在成功登录系统后,如果在固定时间内…

反汇编逆向实战——扫雷辅助制作

一、编程前准备 刚开始是预备知识&#xff0c;如果熟悉的话&#xff0c;可以直接跳到第二部分阅读 在 Windows API 中&#xff0c;SetTimer 函数用于创建一个定时器&#xff0c;并在指定的时间间隔后触发一个定时器消息。以下是关于 SetTimer 函数的介绍&#xff1a; 功能&a…

接口文档设计注意事项

接口名称清晰 一般接口url要求能看得出接口的作用。比如说&#xff0c;查询用户信息&#xff08;queryUserInfo&#xff09;&#xff0c;就是一个不错的接口名称。 接口地址完整 接口的地址&#xff0c;也叫接口的URL地址。即别人调用你的接口&#xff0c;用的是什么URL。比…

【Unity Shader】入门到惊叹(1)基本概念:什么是网格?材质?Shader?

文章目录 一、什么是网格(Mesh)?二、什么是MeshFilter(网格过滤器)?三、什么是MeshRenderer(网格渲染器)?四、什么是材质(Material)?五、什么是Shader(着色器)?一、什么是网格(Mesh)? 如图,模型的三角形面就叫做网格(Mesh),它的本质是一堆顶点数据的规则排…

华为OD机试真题 JavaScript 实现【按身高和体重排队】【2022Q4 100分】,附详细解题思路

一、题目描述 某学校举行运动会&#xff0c;学生们按编号(1、2、3…n)进行标识&#xff0c;现需要按照身高由低到高排列&#xff0c;对身高相同的人&#xff0c;按体重由轻到重排列&#xff1b; 对于身高体重都相同的人&#xff0c;维持原有的编号顺序关系。请输出排列后的学生…

医械围城的觉醒时刻:从“乱世枭雄” 到“剩者为王”

我们现在看到医疗器械行业其实非常的热&#xff0c;不管是投资&#xff0c;还是创业&#xff0c;还有各种跨界进来打劫想分一杯羹的。 但是这个行业是不是一个围城&#xff1f; 真的是进来就可以捡钱吗&#xff1f; 在一片繁荣的景象下&#xff0c;企业的发展存在什么风险&a…

STM32FreeRTOS操作系统移植

移植好的FreeRTOS模板&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1_87VQAWXUl4jTqSCZ0MFjw?pwddw52 提取码&#xff1a;dw52 1.在工程中新建FreeRTOS文件夹 2.把源码source里面的文件全部粘贴进FreeRTOS文件夹中 3.在portable文件中只保留一下文件&#xff0c;…

【剑指offer刷题记录 java版】数组双指针 之 二分搜索

本系列文章记录labuladong的算法小抄中剑指offer题目 【剑指offer刷题记录 java版】数组双指针 之 二分搜索 剑指 Offer 53 - I. 在排序数组中查找数字 I剑指 Offer II 068. 查找插入位置剑指 Offer 04. 二维数组中的查找剑指 Offer II 069. 山峰数组的顶部剑指 Offer II 073. …

java周期性线程池newScheduledThreadPool介绍,多线程下载url文件(断点下载、进度展示、网速展示、剩余时间展示)

文章目录 一&#xff1a;newScheduledThreadPool&#xff08;周期性线程池&#xff09;1.1 特点1.2 核心线程数1.3 创建实例1.4 常用方法1.4.1 schedule方法1.4.2 scheduleAtFixedRate方法1.4.3 scheduleWithFixedDelay方法 二&#xff1a;多线程下载展示文件总大小、剩余时间、…

基于SpringBoot+vue的简历系统设计和实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

ESXi 7.0 U3m HPE (慧与) 定制版 OEM Custom Installer CD

VMware ESXi 7.0 Update 3m - 领先的裸机 Hypervisor (All OEM Customized Installer CDs) ESXi 7.0 U3m Standard (标准版) ESXi 7.0 U3m Dell (戴尔) 定制版 OEM Custom Installer CD ESXi 7.0 U3m HPE (慧与) 定制版 OEM Custom Installer CD ESXi 7.0 U3m Lenovo (联想) 定…