当前位置: 首页 > news >正文

邮件注册(一)验证码发送

通过邮箱实现注册,用户请求验证码完成注册操作。

导入依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>

将验证码丢到消息队列中,再由监听器消费请求

配置完后进行测试:

//JavaMailSender是专门用于发送邮件的对象,自动配置类已经提供了Bean@AutowiredJavaMailSender sender;@Testvoid contextLoads() {//SimpleMailMessage是一个比较简易的邮件封装,支持设置一些比较简单内容SimpleMailMessage message = new SimpleMailMessage();//设置邮件标题message.setSubject("【南京信息工程大学教务处】关于近期学校对您的处分决定");//设置邮件内容message.setText("赵国成同学您好,经监控和教务巡查发现,您近期存在旷课、迟到、早退、上课刷抖音行为," +"现已通知相关辅导员,请手写5000字书面检讨,并于2023年10月7号前交到辅导员办公室。");//设置邮件发送给谁,可以多个,这里就发给你的QQ邮箱message.setTo("786759086@qq.com");//邮件发送者,这里要与配置文件中的保持一致message.setFrom("18061946436@163.com");//OK,万事俱备只欠发送sender.send(message);}

在AccountService中增加方法:

public interface AccountService extends IService<Account> , UserDetailsService {Account findAccountByNameOrEmail(String text);//type区分用户是注册还是更改密码,从而显示不同的文本提示;通过用户ip地址限制请求的频率String RegisterEmailVerifyCode(String type, String email,String ip);
}

在服务代理中实现:

   @Overridepublic String RegisterEmailVerifyCode(String type, String email, String ip) {Random random=new Random();//确保code为六位数int code=random.nextInt(899999)+100000;Map<String ,Object> data=Map.of("type",type,"email",email,"code",code);return type;}

配置消息队列专门处理邮箱,新建RabbitConfig类:

@Configuration
public class RabbitConfig {@Bean("emailQueue")public Queue emailQueue(){return (Queue) QueueBuilder.durable("mail").build();}
}

编写FlowUtils进行过滤:

@Component
public class FlowUtils {@ResourceStringRedisTemplate template;public  boolean limitOnceCheck(String key,int blockTime){//正在冷却的状态if (Boolean.TRUE.equals(template.hasKey(key))){
return false;}else {//如果不在冷却时间内,可以发送邮件,发挥true,并更新冷却时间template.opsForValue().set(key,"",blockTime, TimeUnit.SECONDS);return true;}}
}

根据用户的ip进行过滤:

private boolean verifyLimit(String ip){String key= Const.VERIFY_EMAIL_LIMIT+ip;return flowUtils.limitOnceCheck(key,60);
}

RegisterEmailVerifyCode进行完善:

    @Overridepublic String RegisterEmailVerifyCode(String type, String email, String ip) {if (this.verifyLimit(ip)) {Random random = new Random();//确保code为六位数int code = random.nextInt(899999) + 100000;Map<String, Object> data = Map.of("type", type, "email", email, "code", code);amqpTemplate.convertAndSend("mail", data);template.opsForValue().set(Const.VERIFY_EMAIL_DATA + email, String.valueOf(code), 3, TimeUnit.MINUTES);return null;}else {return "您的请求过于频繁,请稍后再试";}}

同一时间可能会被多次调用,此方法为线程不安全,因此需要上锁synchronized(ip.intern())

创建listener包,新建MailQueueListener类:

@Component
@RabbitListener(queues = "mail")
public class MailQueueListener {@ResourceJavaMailSender sender;@Value("${spring.mail.username}")String username;@RabbitHandlerpublic void sendMailMessage(Map<String,Object> data){String email=(String) data.get("email");Integer code=(Integer) data.get("code");String type =(String) data.get("type");SimpleMailMessage message=switch (type){case "register"->createMessage("欢迎注册","验证码为:"+code+"有效时间为3分钟",email);case "reset"->createMessage("你的密码重置邮件","验证码为:"+code+"有效时间为3分钟",email);default -> null;};if (message==null)return;sender.send(message);}private SimpleMailMessage createMessage(String title,String content,String email){SimpleMailMessage message=new SimpleMailMessage();message.setSubject(title);message.setText(content);message.setTo(email);message.setFrom(username);return message;}}

编写测试接口:

@RestController
@RequestMapping("/api/auth")
public class AuthorizeController {@ResourceAccountService service;@GetMapping("/ask-code")public RestBean<Void> askVerifyCode(@RequestParam String email,@RequestParam String type,HttpServletRequest request) {String message = service.RegisterEmailVerifyCode(type, email, request.getRemoteAddr());return message== null ? RestBean.failure(400, message) : RestBean.success();}}

注意确认在security配置中将测试地址放行。

当请求验证码时,首先进入对应的处理方法,调用service中的RegisterEmailVertifyCode方法,将目标邮箱和类型传入,通过httpServlet得到请求验证码的主机信息,在邮箱验证码方法中,通过random随机生成六位验证码,存入map中,通过amqpTemplate.convertAndSend(“mail”, data)将数据传入消息队列中,此处我们在rabbitconfig中建立了名为mail的emailqueue,接着利用redis数据库进行计时,将对应邮箱的验证码设置为3分钟过期,每次请求的ip地址设置冷却时间60秒,在每次请求前对ip地址进行过滤,最后设置rabbit监听器监听消息队列,一旦消息队列中有邮件数据,则进行读取并利用javaemail进行发送。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

相关文章:

邮件注册(一)验证码发送

通过邮箱实现注册&#xff0c;用户请求验证码完成注册操作。 导入依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><g…...

【网络安全---sql注入(2)】如何通过SQL注入getshell?如何通过SQL注入读取文件或者数据库数据?一篇文章告诉你过程和原理。

前言 本篇博客主要是通过piakchu靶场来讲解如何通过SQL注入漏洞来写入文件&#xff0c;读取文件。通过SQL输入来注入木马来getshell等&#xff0c;讲解了比较详细的过程&#xff1b; 如果想要学习SQL注入原理以及如何进行SQL注入&#xff0c;我也写了一篇详细的SQL注入方法及…...

正点原子嵌入式linux驱动开发——TF-A移植

经过了之前的学习&#xff0c;除了TF-A的详细启动流程仍待更新&#xff0c;TF-A的使用和其对应的大致启动流程已经进行过了学习。但是当我们实际做产品时&#xff0c;硬件平台肯定会和ST官方的有区别&#xff0c;比如DDR容量会改变&#xff0c;自己的硬件没有使用到官方EVK开发…...

GB28181学习(六)——实时视音频点播(数据传输部分)

GB28181系列文章&#xff1a; 总述&#xff1a;https://blog.csdn.net/www_dong/article/details/132515446 注册与注销&#xff1a;https://blog.csdn.net/www_dong/article/details/132654525 心跳保活&#xff1a;https://blog.csdn.net/www_dong/article/details/132796…...

JMeter接口自动化测试(数据驱动)

之前我们的用例数据都是配置在HTTP请求中&#xff0c;每次需要增加&#xff0c;修改用例都需要打开JMeter重新编辑&#xff0c;当用例越来越多的时候&#xff0c;用例维护起来就越来越麻烦&#xff0c;有没有好的方法来解决这种情况呢&#xff1f;我们可以将用例的数据存放在cs…...

数据结构:二叉树(超详解析)

目录​​​​​​​ 1.树概念及结构 1.1树的概念 1.2树的相关概念 1.3树的表示 1.3.1孩子兄弟表示法&#xff1a; 1.3.2双亲表示法&#xff1a;只存储双亲的下标或指针 两节点不在同一树上&#xff1a; 2.二叉树概念及结构 2.1.概念 2.2.特殊的二叉树&#xff1a; 2…...

【考研数学】高等数学第七模块 —— 曲线积分与曲面积分 | 4. 对坐标的曲面积分(第二类曲面积分)与场论初步

文章目录 二、曲面积分2.2 对坐标的曲面积分&#xff08;第二类曲面积分&#xff09;1. 问题产生 —— 流量2. 对坐标的曲面积分的定义&#xff08;了解&#xff09;3. 对坐标的曲面积分的性质4. 对坐标的曲面积分的计算法&#xff08;1&#xff09; 二重积分法&#xff08;2&a…...

使用Thrift实现跨语言RPC调用

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…...

【QT5-程序控制电源-RS232-SCPI协议-上位机-基础样例【1】】

【QT5-程序控制电源-RS232-SCPI协议-上位机-基础样例【1】】 1、前言2、实验环境3、自我总结1、基础了解仪器控制-熟悉仪器2、连接SCPI协议3、选择控制方式-程控方式-RS2324、代码编写 4、熟悉协议-SCPI协议5、测试实验-测试指令&#xff08;1&#xff09;硬件连接&#xff08;…...

leetcode 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零

1049. 最后一块石头的重量 II 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果…...

Error string: Could not load library

启动Rivz时&#xff0c;报错&#xff1a; Error string: Could not load library (Poco exception libg2o_csparse_extension.so.0.1: cannot open shared object file: No such file or directory) [ERROR] [1696572310.529059051]: Failed to load nodelet [/radar_graph_s…...

pom.xml里的标签

pom.xml 是 Maven 项目的配置文件&#xff0c;其中包含了各种配置信息和依赖管理。下面是一些常见的 pom.xml 中的标签和其作用的简要说明&#xff1a; <project>&#xff1a;根标签&#xff0c;定义了整个项目的基本信息和结构。 <groupId>&#xff1a;指定项目所…...

微服务部署的正确策略

微服务部署挑战 单体应用程序的部署意味着您运行单个&#xff08;通常是大型应用程序&#xff09;的多个相同副本。这主要是通过配置 N 个服务器&#xff08;无论是物理服务器还是虚拟服务器&#xff09;并在每台服务器上运行应用程序的 M 个实例来完成。虽然这看起来非常简单…...

C#中的数组探究与学习

目录 C#中的数组一般分为:一.数组定义:为什么要使用数组?什么是数组?C#一维数组for和foreach的区别C#多维数组C#锯齿数组初始化的意义:适用场景:C#中的数组一般分为: ​①.一维数组。 ②.多维数组,也叫矩形数组。 ③.锯齿数组,也叫交错数组。 一.数组定义: 数组…...

计算机网络八股

1、请你说说TCP和UDP的区别 TCP提供面向连接的可靠传输&#xff0c;UDP提供面向无连接的不可靠传输。UDP在很多实时性要求高的场景有很好的表现&#xff0c;而TCP在要求数据准确、对速度没有硬件要求的场景有很好的表现。TCP和UDP都是传输层协议&#xff0c;都是为应用层程序服…...

Waves 14混音特效插件合集mac/win

Waves14是一款音频处理软件&#xff0c;主要用于音频编辑、混音和母带处理。该软件提供了各种插件&#xff0c;包括EQ、压缩、混响、延迟、失真等&#xff0c;以及一些专业的音频处理工具&#xff0c;如L2限幅器、Linear Phase EQ和多频道扬声器管理。 Mac软件下载&#xff1a;…...

Python python-docx 使用教程

openpyxl是Python下的Word库&#xff0c;它能够很容易的对Word文档进行读取 安装方法&#xff1a;pip install python-docx国内镜像安装&#xff1a;pip install -i https://mirrors.aliyun.com/pypi/simple/ python-docx&#xff08;推荐&#xff0c;安装更快&#xff09;中文…...

Mac上protobuf环境构建-java

参考文献 getting-started 官网pb java介绍 maven protobuf插件 简单入门1 简单入门2 1. protoc编译器下载安装 https://github.com/protocolbuffers/protobuf/releases?page10 放入.zshrc中配置环境变量  ~/IdeaProjects/test2/ protoc --version libprotoc 3.12.1  …...

CocosCreator3.8研究笔记(二十二)CocosCreator 动画系统-动画剪辑和动画组件介绍

国庆假期&#xff0c;闲着没事&#xff0c;在家研究技术~ 大家都知道在Cocos Creator3.x 的版本的动画编辑器中&#xff0c;可以实现不用写一行代码就能实现各种动态效果。 Cocos Creator动画编辑器中主要实现关键帧动画&#xff0c;不仅支持位移、旋转、缩放、帧动画&#xff…...

信看课堂-厘米GNSS定位

我们常常说GPS 定位&#xff0c;不过定位远不止GPS定位&#xff0c;通过本节课程&#xff0c;我们将会了解到&#xff0c;原来GPS只是定位的一种&#xff1a; GNSS概述 不同的GNSS系统使用不同的频段来传输导航信号。以下是一些主要的GNSS系统及其相应的频段&#xff0c;用表…...

2023CCPC网络赛(A E)

2023CCPC网络赛(A E) The 2nd Universal Cup. Stage 3: Binjiang - Dashboard - Contest - Universal Cup Judging System A. Almost Prefix Concatenation 思路&#xff1a;首先考虑如何求出每个位置允许失配一次的LCP长度 &#xff0c; 可以二分哈希求LCP &#xff0c; 即…...

使用 python 检测泛洪攻击的案例

使用 python 检测泛洪攻击的案例 本案例只使用python标准库通过执行命令来监控异常请求, 并封锁IP, 不涉及其他第三方库工具. import os import time from collections import Counter# 1、update 命令, 采集CPU的平均负载 def get_cpu_load():"""uptime 命令…...

SCROLLINFO scrollInfo; 2023/10/5 下午3:38:53

2023/10/5 下午3:38:53 SCROLLINFO scrollInfo;scrollInfo.cbSize = sizeof(SCROLLINFO);scrollInfo.fMask = SIF_ALL;//scrollInfo.nMin = 0; // 最小位置//scrollInfo.nMax = nRowCountToShow; // 最大位置//scrollInfo.nPage = nRowCountToShow; // 页面大小//scrollInf…...

Python--控制台获取输入与正则表达式

前言一、控制台获取输入1.1 字符串输入1.2 整数输入1.3 浮点数输入1.4 布尔值输入1.5 列表输入1.6 汇总 二、正则表达式2.1 匹配数字2.2 模式检查2.3 替换字符2.4 切分字符串2.5 搜索并提取匹配的部分2.6 使用捕获组提取匹配的部分2.7 非贪婪匹配2.8 忽略大小写匹配2.9 使用预定…...

网络基础知识面试题1

VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)...

JavaScript系列从入门到精通系列第十五篇:JavaScript中函数的实参介绍返回值介绍以及函数的立即执行

文章目录 一&#xff1a;函数的参数 1&#xff1a;形参如何定义 2&#xff1a;形参的使用规则 二&#xff1a;函数的返回值 1&#xff1a;函数返回值如何定义 2&#xff1a;函数返回值种类 三&#xff1a;实参的任意性 1&#xff1a;方法可以作为实参 2&#xff1a;将匿…...

js中的原型链

编写思路&#xff1a; 简单介绍构造函数介绍原型对象原型对象、实例的关系&#xff0c;从而引出原型链的基本概念 原型链基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。 1. 什么是构造函数 构造函数本身跟普通函数一样&#xff0c;也不存在定义构造函数…...

一文搞懂APT攻击

APT攻击 1. 基本概念2. APT的攻击阶段3. APT的典型案例参考 1. 基本概念 高级持续性威胁&#xff08;APT&#xff0c;Advanced Persistent Threat&#xff09;&#xff0c;又叫高级长期威胁&#xff0c;是一种复杂的、持续的网络攻击&#xff0c;包含高级、长期、威胁三个要素…...

在pandas中通过一列数据映射出另一列的几种思路和方法

如果一句话中出现某个品牌的关键词&#xff0c;那么就将该品牌进行提取&#xff0c;开始我的做法是写了很多elif&#xff0c;如下&#xff1a; def brand_describe(x):if TRUM in x.upper():return "通快"elif BYSTRONIC in x.upper():return "百超"elif …...

数据分析视角中的商业分析学习笔记

数据分析一大堆&#xff0c;结果却是大家早就知道的结论&#xff1f;是工具和方法出问题了吗&#xff1f;真正原因可能是你的思维有误区。 为什么分析的这么辛苦&#xff0c;得出的结论大家早知道&#xff0c;谁谁都不满意&#xff1f;核心原因有3个&#xff1a; 分析之前&am…...

重庆网站建设案例/互联网营销是什么

在javaEE开发中&#xff0c;我们在支持Hibernate之后&#xff0c;想使用Myeclipse自动生成java的Bean和BeanName.hbm.xml文件(Oracle12c为例)&#xff1a; 注&#xff1a;以下提到"BeanName"为您使用的java class name。 1&#xff1a;创建一个java项目让他支持Hiber…...

网站建设技术公司/百度搜索推广方案

所谓八皇后问题&#xff0c;是指在88的国际象棋棋盘上放置8个皇后&#xff0c;保证任意2个皇后都无法互相攻击的问题。如下图所示&#xff0c;国际象棋中的皇后可以向8个方向移动任意格。 任务&#xff1a; 现已在棋盘上摆放了k个皇后&#xff0c;且这k个格子的位置已给出。请…...

b.wordpress/自己做seo网站推广

三次握手 第一次握手&#xff1a; 客户端给服务端发一个 SYN 报文&#xff0c;SYN1&#xff0c;初始序号seqx。此时客户端处于 SYN_SEND 状态 第二次握手&#xff1a; 服务器收到客户端的 SYN 报文之后&#xff0c;会以自己的 SYN 报文作为应答&#xff0c;SYN1&#xff0c…...

增城做网站/2021近期时事新闻热点事件

修改MySQL中字段的类型和长度...

全国美容网站建设/上海搜索优化推广哪家强

前言&#xff1a;前段时间将hadoop01的虚拟机弄的崩溃掉了&#xff0c;也没有备份&#xff0c;重新从hadoop02虚拟上克隆过来的&#xff0c;结果hadoop-eclipse插件一样的编译&#xff0c;居然用不起了&#xff0c;找了3天的原因&#xff0c;最后还是没有解决&#xff0c;只能用…...

中国菲律宾引渡/天津seo培训机构

长期以来&#xff0c;好多网友对郑州大学入选双一流高校充满异议&#xff0c;原因就是所谓的郑州大学没有A类学科&#xff0c;那么A类学科是什么意思呢&#xff1f;说A类学科要从2002年第1轮学科评估说起&#xff0c;当年要求必须是具有研究生培养资格和学位授予权的一级学科&a…...