网站重构,物流网站建设策划书怎么写,天津网站建设维护,商标注册费用最近想给自己的项目在注册时加点安全校验#xff0c;本想着使用短信验证码#xff0c;奈何囊中羞涩只能退而求次改用QQ邮箱验证注册~
一.需求分析 场景#xff1a;用户输入自己的邮箱#xff0c;点击获取验证码#xff0c;后台会发送一封邮件到对应邮箱中。 分析#x…最近想给自己的项目在注册时加点安全校验本想着使用短信验证码奈何囊中羞涩只能退而求次改用QQ邮箱验证注册~
一.需求分析 场景用户输入自己的邮箱点击获取验证码后台会发送一封邮件到对应邮箱中。 分析防止刷爆邮箱可以限制一分钟内只能获取一次。 前端期限内禁用button按钮。后端存入redis设置过期时间请求先判断redis中是否有数据。
二.环境准备
(1) 邮箱环境 在QQ邮箱中开启SMTP服务获取授权码 网页版进入邮箱点击设置中的账户 往下翻可以看到如下服务开关点击开启
点击开启后会得到一串授权码后端程序中需要用到。
可能会要求完成相关安全验证
(2) 后端环境 大概率是在web项目中使用到因此我们创建一个SpringBoot工程 创建好项目后在pom文件中导入操作邮箱所需jar包 !--QQ邮箱验证码所需jar包--dependencygroupIdjavax.activation/groupIdartifactIdactivation/artifactIdversion1.1.1/version/dependencydependencygroupIdjavax.mail/groupIdartifactIdmail/artifactIdversion1.4.7/version/dependencydependencygroupIdorg.apache.commons/groupIdartifactIdcommons-email/artifactIdversion1.4/version/dependency由于我们需要在spring项目使用redis缓存验证码因此还要导入redis的jar包 !-- 使用redis缓存验证码时效--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency在yml文件中配置redis,设置了redis密码记得加上密码配置
spring:redis:# redis数据库索引(默认为0)我们使用索引为3的数据库避免和其他数据库冲突database: 3# redis服务器地址默认为localhosthost: localhost# redis端口默认为6379port: 6379三.后端程序
(1) 效果实现
发送邮箱应该算个工具因此我们可以在工具类中写入如下代码
package com.example.utils;import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;public class SendMailUtil {/*** 发送邮件代码** param targetEmail 目标用户邮箱* param authCode 发送的验证码*/public static void sendEmailCode(String targetEmail, String authCode) {try {// 创建邮箱对象SimpleEmail mail new SimpleEmail();// 设置发送邮件的服务器mail.setHostName(smtp.qq.com);// 你的邮箱号 上文开启SMTP获得的授权码mail.setAuthentication(158xxx69qq.com, fbsxxxxxsijdj);// 发送邮件 你的邮箱号发送时用的昵称mail.setFrom(15xxx69qq.com, 观止);// 使用安全链接mail.setSSLOnConnect(true);// 接收用户的邮箱mail.addTo(targetEmail);// 邮件的主题(标题)mail.setSubject(注册验证码);// 邮件的内容mail.setMsg(您的验证码为: authCode(一分钟内有效));// 发送mail.send();} catch (EmailException e) {e.printStackTrace();}}
}编写如下接口
RestController
public class SendMail {PostMapping(/getCode)ResponseBodypublic String mail(RequestParam(targetEmail) String targetEmail) {// 随机生成六位数验证码String authCode String.valueOf(new Random().nextInt(899999) 100000);SendMailUtil.sendEmailCode(targetEmail,authCode);return ok;}
}
让我们测试一下接口
GET http://localhost:8080/getCode?targetEmail35xxxx947qq.com可以看到如下效果
如此我们初步效果就已经实现啦~
(3) 缓存改进
上述程序我们疯狂发送请求可以一直发送邮箱这显然不是我们所期待的接下来我们加入redis来改进一下。
RestController
public class SendMail {Resourceprivate RedisTemplateString, String redisTemplate new RedisTemplate();/*** param targetEmail 用户邮箱* return*/GetMapping(/getCode)ResponseBodypublic String mail(RequestParam(targetEmail) String targetEmail) {// 发送前先看下我们是否已经缓存了验证码String yzm redisTemplate.opsForValue().get(yzm);// 判断是否存在if (yzm null){// 生成六位数验证码int authNum new Random().nextInt(899999) 100000;String authCode String.valueOf(authNum);// 不存在我们发送邮箱给用户SendMailUtil.sendEmailCode(targetEmail, 你的验证码为: authCode (五分钟内有效));// 存入redis中设置有效期为1分钟redisTemplate.opsForValue().set(yzm, authCode, 1, TimeUnit.MINUTES);return 发送成功;}// 存在直接返回不再发送邮箱~return 请勿重复发送验证码;}}如此再次测试可以发现疯狂点击不再产生效果成功被拦截如此安全了许多
至此我们开始想要的效果便已经在小demo中实现了接下来可以引入正式自己项目啦
四.前端(补充)
用原生js简单写了一个界面感兴趣的可以看一看
代码如下
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
divinput idmail typetextbutton idgetCode获取验证码/button
/div
script/*按钮禁用60秒,并显示倒计时*/function disabledButton() {const getCode document.querySelector(#getCode)getCode.disabled truelet second 60;const intervalObj setInterval(function () {getCode.innerText 请 second 秒后再重试if (second 0) {getCode.innerText 获取验证码getCode.disabled falseclearInterval(intervalObj);}second--;}, 1000);}document.querySelector(#getCode).addEventListener(click, function () {const mail document.querySelector(#mail)let xhr new XMLHttpRequest();xhr.open(GET, http://localhost:8080/getCode?targetEmail mail.value, true);xhr.send();xhr.onreadystatechange function () {if (xhr.readyState 4) {alert(xhr.response);disabledButton()}}})/script
/body
/html