使用TIANAI-CAPTCHA進行行為驗證碼的生成和緩存的二次校驗

1.導入依賴:
<dependency><groupId>cloud.tianai.captcha</groupId><artifactId>tianai-captcha-springboot-starter</artifactId><version>1.5.2</version>
</dependency>
2.在application.yml中配置驗證碼相關配置:
# 滑塊驗證碼配置, 詳細請看 cloud.tianai.captcha.autoconfiguration.ImageCaptchaProperties 類
captcha:# 如果項目中使用到了redis,滑塊驗證碼會自動把驗證碼數據存到redis中, 這里配置redis的key的前綴,默認是captcha:sliderprefix: captcha# 驗證碼過期時間,默認是2分鐘,單位毫秒, 可以根據自身業務進行調整expire:# 默認緩存時間 2分鐘default: 10000# 針對 點選驗證碼 過期時間設置為 2分鐘, 因為點選驗證碼驗證比較慢,把過期時間調整大一些WORD_IMAGE_CLICK: 20000# 使用加載系統自帶的資源, 默認是 false(這里系統的默認資源包含 滑動驗證碼模板/旋轉驗證碼模板,如果想使用系統的模板,這里設置為true)init-default-resource: true# 緩存控制, 默認為false不開啟local-cache-enabled: false# 緩存開啟后,驗證碼會提前緩存一些生成好的驗證數據, 默認是20local-cache-size: 20# 緩存開啟后,緩存拉取失敗后等待時間 默認是 5秒鐘local-cache-wait-time: 5000# 緩存開啟后,緩存檢查間隔 默認是2秒鐘local-cache-period: 2000# 配置字體包,供文字點選驗證碼使用,可以配置多個,不配置使用默認的字體font-path:- classpath:font/SimHei.ttfsecondary:# 二次驗證, 默認false 不開啟enabled: false# 二次驗證過期時間, 默認 2分鐘expire: 120000# 二次驗證緩存key前綴,默認是 captcha:secondarykeyPrefix: "captcha:secondary"
3.接入springboot進行驗證碼的開發:
controller:
@RestController
@RequestMapping("/system/captcha")
public class CaptchaController {@Resourceprivate CaptchaService captchaService;@GetMapping("/get-slider-image")@ApiOperation("生成滑塊驗證碼圖片")public CommonResult<CaptchaResponse<ImageCaptchaVO>> getSliderCaptchaImage() {return success(captchaService.getSliderCaptchaImage());}@PostMapping("/check")@ApiOperation("滑塊驗證碼確認")public CommonResult<Boolean> checkCaptchaImage(HttpServletRequest request,@Valid @RequestBody CaptchaImageVo captchaImageVo) {return success(captchaService.checkCaptchaImage(captchaImageVo));}}
service:
/*** 驗證碼 Service 接口*/
public interface CaptchaService {/*** 是否開啟圖片驗證碼** @return 是否*/Boolean isCaptchaEnable();/*** 獲得 uuid 對應的驗證碼** @param uuid 驗證碼編號* @return 驗證碼*/String getCaptchaCode(String uuid);/*** 刪除 uuid 對應的驗證碼** @param uuid 驗證碼編號*/void deleteCaptchaCode(String uuid);/*** 圖片驗證碼驗證**/Boolean checkCaptchaImage(CaptchaImageVo captchaImageVo);/*** 獲得驗證碼圖片** @return 驗證碼圖片*/CaptchaResponse<ImageCaptchaVO> getSliderCaptchaImage();/*** 判斷對應的滑動驗證碼是否通過**/Boolean alreadyValid(String uuid) ;
}
impl:
/*** 驗證碼 Service 實現類*/
@Service
@Slf4j
public class CaptchaServiceImpl implements CaptchaService {@Value("${captcha.expire.defult}")private Duration timeout;@Resourceprivate MyResourceStoreProperties myResourceStoreProperties;@Resourceprivate CaptchaRedisDAO captchaRedisDAO;@Resourceprivate ImageCaptchaApplication application;@Resourceprivate CacheStore cacheStore;@Resourceprivate ImageCaptchaProperties imageCaptchaProperties;@Overridepublic String getCaptchaCode(String uuid) {return captchaRedisDAO.get(uuid);}@Overridepublic void deleteCaptchaCode(String uuid) {captchaRedisDAO.delete(uuid);}@Overridepublic Boolean checkCaptchaImage(CaptchaImageVo captchaImageVo) {Boolean isPass = application.matching(captchaImageVo.getId(), captchaImageVo.getImageCaptchaTrack());captchaRedisDAO.set(captchaImageVo.getId(), isPass.toString(), timeout);return isPass;}@Overridepublic Boolean alreadyValid(String uuid) {if (captchaRedisDAO.get(uuid) != null) {boolean result = Boolean.parseBoolean(captchaRedisDAO.get(uuid));captchaRedisDAO.delete(uuid);return result;}return false;}@Overridepublic CaptchaResponse<ImageCaptchaVO> getSliderCaptchaImage() {//加載模板myResourceStoreProperties.MyResourceStore();CaptchaResponse<ImageCaptchaVO> response = application.generateCaptcha(CaptchaTypeConstant.SLIDER);Map<String, Object> data = cacheStore.getCache(imageCaptchaProperties.getPrefix().concat(":").concat(response.getId()));//動態設置偏移容錯data.put("tolerant", 0.2);cacheStore.setCache(imageCaptchaProperties.getPrefix().concat(":").concat(response.getId()), data, 20000L, TimeUnit.MILLISECONDS);return response;}}
注入的自定義類:
@Component
public class MyResourceStoreProperties extends DefaultResourceStore {public void MyResourceStore() {// 滑塊驗證碼 模板 (系統內置)Map<String, Resource> template1 = new HashMap<>(4);template1.put(SliderCaptchaConstant.TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/active.png")));template1.put(SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/fixed.png")));template1.put(SliderCaptchaConstant.TEMPLATE_MATRIX_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/matrix.png")));Map<String, Resource> template2 = new HashMap<>(4);template2.put(SliderCaptchaConstant.TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/active.png")));template2.put(SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/fixed.png")));template2.put(SliderCaptchaConstant.TEMPLATE_MATRIX_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/matrix.png")));// 1. 添加一些模板addTemplate(CaptchaTypeConstant.SLIDER, template1);addTemplate(CaptchaTypeConstant.SLIDER, template2);// 2. 添加自定義背景圖片int dayOfWeek=DateUtil.dayOfWeek(new Date())-1;addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/slider.jpg"));//addResource(CaptchaTypeConstant.SLIDER, new Resource("URL", "https://soarway-fangpiao-backup-dev.oss-cn-hangzhou.aliyuncs.com/slider-"+dayOfWeek+".jpg"));}}
@Repository
public class CaptchaRedisDAO {@Resourceprivate StringRedisTemplate stringRedisTemplate;public String get(String uuid) {String redisKey = formatKey(uuid);return stringRedisTemplate.opsForValue().get(redisKey);}public void set(String uuid, String code, Duration timeout) {String redisKey = formatKey(uuid);stringRedisTemplate.opsForValue().set(redisKey, code, timeout);}public void delete(String uuid) {String redisKey = formatKey(uuid);stringRedisTemplate.delete(redisKey);}private static String formatKey(String uuid) {return String.format(CAPTCHA_CODE.getKeyTemplate(), uuid);}}
?4.驗證碼的雙重驗證:

防止惡意劫持和重放攻擊

第一次校驗:

@Overridepublic Boolean checkCaptchaImage(CaptchaImageVo captchaImageVo) {Boolean isPass = application.matching(captchaImageVo.getId(), captchaImageVo.getImageCaptchaTrack());captchaRedisDAO.set(captchaImageVo.getId(), isPass.toString(), timeout);return isPass;}

? ? 用戶->>前端: ?1.拖動滑塊完成驗證
前端->>后端: 發送滑塊ID+軌跡數據 (checkCaptchaImage)
后端->>后端: 計算軌跡匹配度
后端->>Redis: 存儲驗證結果 (key:滑塊ID, value:true/false)
后端->>前端: 返回實時結果

第二次校驗:

@Overridepublic Boolean alreadyValid(String uuid) {if (captchaRedisDAO.get(uuid) != null) {boolean result = Boolean.parseBoolean(captchaRedisDAO.get(uuid));captchaRedisDAO.delete(uuid);return result;}return false;}

? ? 用戶->>前端: 2. 提交登錄表單
前端->>后端: 發送表單數據+滑塊ID (alreadyValid)
后端->>Redis: 讀取驗證結果
Redis->>后端: 返回預存結果
后端->>Redis: 刪除該滑塊ID的緩存
后端->>前端: 返回最終驗證結果

這樣即使黑客獲取了第一次驗證成功的請求,也無法重復使用該滑塊ID進行二次驗證,因為結果在 alreadyValid 調用后已被刪除。這種設計有效防止了重放攻擊,同時優化了系統性能

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89753.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89753.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89753.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

db.refresh()的重復使用和db.rollback()

db.refresh()在 SQLAlchemy 中&#xff0c;db.refresh() 用于從數據庫中重新加載對象的狀態&#xff0c;確保對象屬性與數據庫中的實際數據保持一致。下面詳細介紹其使用場景和作用&#xff1a;1.獲取數據庫生成的值當數據庫自動生成字段&#xff08;如自增 ID、默認值、觸發器…

《Web安全之機器學習入門》讀書筆記總結

目錄 一、案例總結 1、基礎知識 &#xff08;1&#xff09;第1章 通向智能安全的旅程 &#xff08;2&#xff09;第2章 打造機器學習工具箱 &#xff08;3&#xff09;第3章 機器學習概述 &#xff08;4&#xff09;第4章 Web安全基礎 2、安全案例 &#xff08;1&#…

github 近期熱門項目-2025.7.20

github 近期熱門項目-2025.7.20 GitHub 上近期熱門或趨勢項目的信息可以從多個來源獲取,包括 GitHub Trending 頁面、技術社區推薦、以及各大技術媒體的報道。以下是一些近期在 GitHub 上備受關注的項目類別和示例: 1. AI 與機器學習項目 隨著 AI 技術的快速發展,許多開源…

使用Python清理Excel中的空行和單元格內部空行:初學者指南

前言 作為數據處理人員或辦公室工作者,你可能經常遇到Excel文件中存在多余空行或單元格內有多余空行的問題。這些不必要的空白會影響數據的美觀性,更重要的是會給后續的數據分析、合并或處理帶來麻煩。本文將介紹一個簡單的Python腳本,幫助你高效地解決這些問題。 很多工具…

華為歐拉系統(openEuler)安裝 Docker 容器完整教程

&#x1f525; 前言&#xff1a;在國產化操作系統日益普及的當下&#xff0c;華為歐拉系統&#xff08;openEuler&#xff09;憑借其穩定性和安全性受到不少用戶青睞。但 Docker 官方暫未提供對 openEuler 的原生支持&#xff0c;不過好在 openEuler 與 CentOS 底層架構兼容&am…

數據結構--JDK17新增語法和順序表

一.yield關鍵字用于switch語句上的case代碼塊的返回值舉例&#xff1a;二.var關鍵字作用&#xff1a;當類型名字較長時可以簡化代碼。注意事項&#xff1a;1.不能使用var來聲明字段2.不能使用var來聲明方法參數3.不能使用var來聲明方法返回類型4.使用時必須初始化&#xff0c;但…

1 滲透基礎

目錄 基礎前沿 1 vulhub環境搭建 1 proxychains工具&#xff1a;編輯配置文件 2 docker docker環境搭建 配置docker的代理&#xff1a; 2 nginx編譯安裝--FPM 1 php.ini 2 php-fpm 3 nginx 4 nginx php-fpm php 1 基本角色分工 2. 請求處理全流程 步驟 1&#xff…

基于Java+SpringBoot 的榆林特色旅游網站

源碼編號&#xff1a;S678源碼名稱&#xff1a;基于SpringBoot 的榆林特色旅游網站用戶類型&#xff1a;雙角色&#xff0c;用戶、管理員數據庫表數量&#xff1a;22 張表主要技術&#xff1a;Java、Vue、ElementUl 、SpringBoot、Maven運行環境&#xff1a;Windows/Mac、JDK1…

Python設計模式深度解析:單例模式(Singleton Pattern)完全指南

Python設計模式深度解析&#xff1a;單例模式&#xff08;Singleton Pattern&#xff09;完全指南前言什么是單例模式&#xff1f;單例模式的三個關鍵要素基礎實現&#xff1a;異常控制式單例Python中的經典單例實現1. 使用 __new__ 方法實現2. 線程安全的單例實現3. 裝飾器實現…

LVS 原理詳解及部署(包含實驗案例)

一、集群和分布式簡介1.系統性能擴展方式Scale Up&#xff08;向上擴展&#xff09;&#xff1a;通過增強單臺服務器的硬件性能&#xff08;如提升 CPU、內存、存儲等&#xff09;來提高處理能力&#xff0c;適用于業務初期或對單點性能要求高的場景。這種方式簡單易行&#xf…

兩個路由器通過不同的網段互聯

一&#xff0c;實驗拓撲圖&#xff1a;二、實驗說明 &#xff1a;在兩個接口配置好兩個不同網段的的ip地址后是不能相互通信的。經過測試用ospf把兩個網段宣告進area 0 是行不通的。最后我們通過靜態路由來配置&#xff0c;遇到一個最大的問題是&#xff0c;我們的下一跳地址應…

Python趣味算法:冒泡排序——從理論到極致優化

排序算法是程序員的必修課,而冒泡排序是理解算法思維的絕佳起點。本文將深入解析冒泡排序的7種優化技巧,通過可視化演示+多維度性能分析,帶你徹底掌握這一經典算法! 看在每天堅持分享有趣知識的份上,點個關注吧(づ ̄ 3 ̄)づ 關注是我更新的動力 ̄︶ ̄? ̄︶ ̄?) 作者會…

[simdjson] document_stream | iterate_many() | batch_size | 線程加速 | 輕量handle

第七章&#xff1a;文檔流 歡迎回來 在前面的章節中&#xff0c;我們學習了如何使用解析器結合填充字符串獲取表示JSON根節點的文檔&#xff0c;并通過按需API&#xff08;On-Demand API&#xff09;遍歷值、對象和數組&#xff0c;同時使用simdjson_result進行錯誤處理。 到…

【機器學習】向量數據庫選型指南:企業內網部署場景

向量數據庫選型指南&#xff1a;企業內網部署場景一、選型背景與關鍵需求 在企業級機器學習應用中&#xff0c;特別是涉及圖片、視頻等非結構化數據的場景&#xff0c;向量數據庫已成為核心基礎設施。傳統數據庫難以高效處理高維向量的相似度檢索需求&#xff08;如圖片相似性搜…

Django母嬰商城項目實踐(八)- 數據渲染與顯示之首頁

8、數據渲染與顯示 1 概述 Django作為Web框架,需要一種很便利的方法動態地生成HTML網頁,因此有了模板這個概念。模板包含所需HTML的部分代碼以及一些特殊語法,特殊語法用于描述如何將視圖傳遞的數據動態插入HTML網頁中。 Django可以配置一個或多個模板引擎(甚至是0個,如前…

Redis常見線上問題

文章目錄 Redis常見線上問題 引言 報告背景與目的 Redis版本與環境說明 性能瓶頸問題 慢查詢分析與優化 高CPU與網絡延遲 內存管理問題 內存碎片成因與優化 BigKey與內存溢出 數據一致性與高可用問題 主從同步延遲 腦裂問題與解決方案 持久化機制問題 RDB與AOF對比 核心特性對比…

Typecho博客集成阿里云CDN+OSS實現全站加速方案

文章目錄 Typecho博客系統集成阿里云CDN和OSS實現靜態資源加速 引言 一、技術選型與準備工作 1.1 為什么選擇阿里云CDN+OSS組合 1.2 準備工作 二、OSS存儲桶創建與配置 2.1 創建OSS存儲桶 2.2 配置Bucket權限 2.3 配置跨域訪問(CORS) 三、CDN加速配置 3.1 添加CDN域名 3.2 配置…

計算機畢業設計Java網咖管理系統 Java技術實現的網咖綜合管理系統開發 基于Spring Boot框架的網咖運營管理系統設計

計算機畢業設計Java網咖管理系統e0btvq7l &#xff08;配套有源碼 程序 mysql數據庫 論文&#xff09;本套源碼可以先看具體功能演示視頻領取&#xff0c;文末有聯xi 可分享隨著互聯網技術的飛速發展和電子競技的全球興起&#xff0c;網咖作為一種新興的休閑娛樂場所&#xff0…

Kotlin main函數

main() 函數 來仔細看看 main() 函數。實際上&#xff0c;它就是一個很常見的函數&#xff1a;你可以對它做任何你能對普通函數做的事。唯一的不同是&#xff1a;它是程序的入口點&#xff08;entry point&#xff09;。這意味著程序的執行從調用這個函數開始。 我們來拆解一下…

深入理解 Spring:事務管理與事件機制全解析

文章目錄前言一、Spring 事務管理&#xff08;Transaction Management&#xff09;1. 使用 Transactional 管理事務2. 核心屬性說明3. 事務傳播行為詳解&#xff08;Propagation&#xff09;4. 異常回滾策略分析5. 底層原理剖析&#xff08;源碼級&#xff09;二、Spring 事件機…