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 事件机…