引入QQ郵箱發(fā)送驗證碼進行安全校驗功能實現(xiàn)
最近想給自己的項目在注冊時加點安全校驗,本想著使用短信驗證碼,奈何囊中羞澀只能退而求次改用QQ郵箱驗證注冊~
一.需求分析
- 場景:用戶輸入自己的郵箱,點擊獲取驗證碼,后臺會發(fā)送一封郵件到對應(yīng)郵箱中。
- 分析:防止刷爆郵箱,可以限制一分鐘內(nèi)只能獲取一次。
- 前端:期限內(nèi)禁用button按鈕。
- 后端:存入redis設(shè)置過期時間,請求先判斷redis中是否有數(shù)據(jù)。
二.環(huán)境準(zhǔn)備
(1) 郵箱環(huán)境
在QQ郵箱中開啟SMTP服務(wù),獲取授權(quán)碼
1.網(wǎng)頁版:進入郵箱,點擊設(shè)置中的賬戶
2.往下翻可以看到如下服務(wù)開關(guān),點擊開啟
點擊開啟后會得到一串授權(quán)碼,后端程序中需要用到。
3.可能會要求完成相關(guān)安全驗證
(2) 后端環(huán)境
大概率是在web項目中使用到,因此我們創(chuàng)建一個SpringBoot工程
1.創(chuàng)建好項目后在pom文件中導(dǎo)入操作郵箱所需jar包
<!--QQ郵箱驗證碼所需jar包--> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-email</artifactId> <version>1.4</version> </dependency>
2.由于我們需要在spring項目使用redis緩存驗證碼因此還要導(dǎo)入redis的jar包
<!-- 使用redis緩存驗證碼時效--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
3.在yml文件中配置redis,設(shè)置了redis密碼記得加上密碼配置
spring: redis: # redis數(shù)據(jù)庫索引(默認(rèn)為0),我們使用索引為3的數(shù)據(jù)庫,避免和其他數(shù)據(jù)庫沖突 database: 3 # redis服務(wù)器地址(默認(rèn)為localhost) host: localhost # redis端口(默認(rèn)為6379) port: 6379
三.后端程序
(1) 效果實現(xiàn)
1.發(fā)送郵箱應(yīng)該算個工具,因此我們可以在工具類中寫入如下代碼
package com.example.utils; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.SimpleEmail; public class SendMailUtil { /** * 發(fā)送郵件代碼 * * @param targetEmail 目標(biāo)用戶郵箱 * @param authCode 發(fā)送的驗證碼 */ public static void sendEmailCode(String targetEmail, String authCode) { try { // 創(chuàng)建郵箱對象 SimpleEmail mail = new SimpleEmail(); // 設(shè)置發(fā)送郵件的服務(wù)器 mail.setHostName("smtp.qq.com"); // "你的郵箱號"+ "上文開啟SMTP獲得的授權(quán)碼" mail.setAuthentication("158xxx69@qq.com", "fbsxxxxxsijdj"); // 發(fā)送郵件 "你的郵箱號"+"發(fā)送時用的昵稱" mail.setFrom("15xxx69@qq.com", "觀止"); // 使用安全鏈接 mail.setSSLOnConnect(true); // 接收用戶的郵箱 mail.addTo(targetEmail); // 郵件的主題(標(biāo)題) mail.setSubject("注冊驗證碼"); // 郵件的內(nèi)容 mail.setMsg("您的驗證碼為:" + authCode+"(一分鐘內(nèi)有效)"); // 發(fā)送 mail.send(); } catch (EmailException e) { e.printStackTrace(); } } }
2.編寫如下接口
@RestController public class SendMail { @PostMapping("/getCode") @ResponseBody public String mail(@RequestParam("targetEmail") String targetEmail) { // 隨機生成六位數(shù)驗證碼 String authCode = String.valueOf(new Random().nextInt(899999) + 100000); SendMailUtil.sendEmailCode(targetEmail,authCode); return "ok"; } }
3.讓我們測試一下接口
GET http://localhost:8080/getCode?targetEmail=35xxxx947@qq.com
可以看到如下效果:
如此我們初步效果就已經(jīng)實現(xiàn)啦~
(2) 緩存改進
上述程序我們瘋狂發(fā)送請求可以一直發(fā)送郵箱,這顯然不是我們所期待的,接下來我們加入redis來改進一下。
@RestController public class SendMail { @Resource private RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); /** * @param targetEmail 用戶郵箱 * @return */ @GetMapping("/getCode") @ResponseBody public String mail(@RequestParam("targetEmail") String targetEmail) { // 發(fā)送前先看下我們是否已經(jīng)緩存了驗證碼 String yzm = redisTemplate.opsForValue().get("yzm"); // 判斷是否存在 if (yzm == null){ // 生成六位數(shù)驗證碼 int authNum = new Random().nextInt(899999) + 100000; String authCode = String.valueOf(authNum); // 不存在,我們發(fā)送郵箱給用戶 SendMailUtil.sendEmailCode(targetEmail, "你的驗證碼為:" + authCode + "(五分鐘內(nèi)有效)"); // 存入redis中,設(shè)置有效期為1分鐘 redisTemplate.opsForValue().set("yzm", authCode, 1, TimeUnit.MINUTES); return "發(fā)送成功"; } // 存在,直接返回,不再發(fā)送郵箱~ return "請勿重復(fù)發(fā)送驗證碼"; } }
如此再次測試,可以發(fā)現(xiàn)瘋狂點擊不再產(chǎn)生效果,成功被攔截,如此安全了許多
至此我們開始想要的效果便已經(jīng)在小demo中實現(xiàn)了,接下來可以引入正式自己項目啦
四.前端(補充)
用原生js簡單寫了一個界面,感興趣的可以看一看
代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <input id="mail" type="text"> <button id="getCode">獲取驗證碼</button> </div> <script> /*按鈕禁用60秒,并顯示倒計時*/ function disabledButton() { const getCode = document.querySelector("#getCode") getCode.disabled = true let second = 60; const intervalObj = setInterval(function () { getCode.innerText = "請" + second + "秒后再重試" if (second === 0) { getCode.innerText = "獲取驗證碼" getCode.disabled = false clearInterval(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>
到此這篇關(guān)于引入QQ郵箱發(fā)送驗證碼進行安全校驗的文章就介紹到這了,更多相關(guān)QQ郵箱發(fā)送驗證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis注解開發(fā)單表、多表操作的實現(xiàn)代碼
這篇文章主要介紹了Mybatis高級:Mybatis注解開發(fā)單表操作,Mybatis注解開發(fā)多表操作,構(gòu)建sql語句,綜合案例學(xué)生管理系統(tǒng)使用接口注解方式優(yōu)化,需要的朋友可以參考下2021-02-02詳解java 三種調(diào)用機制(同步、回調(diào)、異步)
這篇文章主要介紹了java 三種調(diào)用機制(同步、回調(diào)、異步),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04玩轉(zhuǎn)spring boot 結(jié)合AngularJs和JDBC(4)
玩轉(zhuǎn)spring boot,這篇文章主要介紹了結(jié)合AngularJs和JDBC,玩轉(zhuǎn)spring boot,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01使用Java實現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫
這篇文章主要為大家詳細介紹了如何使用Java實現(xiàn)動態(tài)生成MySQL數(shù)據(jù)庫,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02