2025-03-21
工具运维
0

目录

tianai-captcha
前端集成
SpringBoot 集成
添加Maven依赖
配置 application.yml
生成和验证验证码
验证码数据验证
高级功能与自定义配置
自定义验证码资源
二次验证增强安全
性能调优建议
注意事项
环境要求
安全实践
移动端适配
总结

在网络安全的战场上,验证码作为区分人类用户与机器程序的第一道防线,其重要性不言而喻。然而,传统字符验证码存在用户体验差、机器识别率高等问题,难以平衡安全性与易用性。

今天我们来聊一下 "开源界最好用的行为验证码工具 tianai-captcha"

tianai-captcha

基于以上问题,tianai-captcha(简称TAC)应运而生,它是一款基于Java开发的行为验证码系统,通过滑动、旋转、点选等交互方式,在提升安全性的同时显著改善了用户体验。该项目已加入Dromara开源社区,被誉为"开源界最好用的行为验证码工具"。

项目资源

多样化的验证码类型

tianai-captcha支持丰富的行为验证码类型,包括:

  • 滑块验证码:通过轨迹分析识别人类操作特征

  • 旋转验证码:基于角度匹配的防护方案

  • 滑动还原验证码:动态生成算法确保每次挑战唯一

  • 文字点选验证码:语义化交互提升无障碍体验

  • 图标验证码:图形化识别,提升趣味性

  • 语序验证码:要求用户按正确顺序排列词语

  • 刮刮乐验证码:模拟现实刮奖体验

安全性与用户体验的完美平衡

与传统验证码相比,tianai-captcha在多个维度表现出色:

特性tianai-captcha传统验证码
防护强度⭐⭐⭐⭐⭐⭐⭐
用户完成时间约2.3秒约5.8秒
移动端适配全自动响应式需手动调整
用户完成率高达92%约85%
恶意请求拦截率98.7%-

技术优势

  • 轻量级设计:核心包仅2.3MB,对系统资源消耗极小

  • 高并发支持:分布式缓存支持下,验证数据TPS可达12,000+

  • 快速响应:平均响应时间控制在150-200ms以内

  • 多端兼容:支持PC端、移动端及iOS/Android内嵌Webview

前端集成

兼容性:Chrome、Firefox、Safari、Opera、主流手机浏览器、iOS 及 Android上的内嵌Webview

框架支持:H5、Angular、React、Vue2、Vue3

1、 将前端sdk的具体js文件下载到项目中、或者放到某个可以访问到地方,比如oss之类的可以被浏览器访问到的地方供加载函数调用 tac下载地址 https://gitee.com/dromara/tianai-captcha/releases/tag/tianai-captcha-1.5.3 (opens new window),里面包含tac.js和tac.css等

2、 引入初始化函数 load.js下载地址 https://minio.tianai.cloud/public/static/captcha/js/load.min.js (opens new window)可自己将load.js下载到本地(右键->另存为)

html
<html> <head> <!-- 引入验证码初始化js --> <script src="load.min.js"></script> </head> <body>...</body> </html>

3、创建一个div块用于渲染验证码, 该div用于装载验证码

html
<div id="captcha-box"></div>

4、在需要调用验证码的时候执行加载验证码方法

js
function login() { // config 对象为TAC验证码的一些配置和验证的回调 const config = { // 生成接口 (必选项,必须配置, 要符合tianai-captcha默认验证码生成接口规范) requestCaptchaDataUrl: "/gen", // 验证接口 (必选项,必须配置, 要符合tianai-captcha默认验证码校验接口规范) validCaptchaUrl: "/check", // 验证码绑定的div块 (必选项,必须配置) bindEl: "#captcha-box", // 验证成功回调函数(必选项,必须配置) validSuccess: (res, c, tac) => { // 销毁验证码服务 tac.destroyWindow(); console.log("验证成功,后端返回的数据为", res); // 调用具体的login方法 login(res.data.token) }, // 验证失败的回调函数(可忽略,如果不自定义 validFail 方法时,会使用默认的) validFail: (res, c, tac) => { console.log("验证码验证失败回调...") // 验证失败后重新拉取验证码 tac.reloadCaptcha(); }, // 刷新按钮回调事件 btnRefreshFun: (el, tac) => { console.log("刷新按钮触发事件...") tac.reloadCaptcha(); }, // 关闭按钮回调事件 btnCloseFun: (el, tac) => { console.log("关闭按钮触发事件...") tac.destroyWindow(); } } // 一些样式配置, 可不传 let style = { logoUrl: null// 去除logo // logoUrl: "/xx/xx/xxx.png" // 替换成自定义的logo } // 这里分享一些作者自己调的样式供参考 // const style = { // // 按钮样式 // btnUrl: "https://minio.tianai.cloud/public/captcha-btn/btn3.png", // // 背景样式 // bgUrl: "https://minio.tianai.cloud/public/captcha-btn/btn3-bg.jpg", // // logo地址 // logoUrl: "https://minio.tianai.cloud/public/static/captcha/images/logo.png", // // 滑动边框样式 // moveTrackMaskBgColor: "#f7b645", // moveTrackMaskBorderColor: "#ef9c0d" // } // -------------- 拉起TAC验证码 ----------------- // 参数1: tac文件的URL地址前缀, 目录里包含 tac的js和css等文件, // 比如参数为: http://xxxx/tac/, 该js会自动加载 http://xxxx/tac/js/tac.min.js 、http://xxxx/tac/css/tac.css等 // 具体的js文件可以在 https://gitee.com/tianai/tianai-captcha-web-sdk/releases/tag/1.2 下载 // 参数2: tac验证码相关配置 // 参数3: tac窗口一些样式配置 window.initTAC("./tac", config, style).then(tac => { tac.init(); // 调用init则显示验证码 }).catch(e => { console.log("初始化tac失败", e); }) }

SpringBoot 集成

对于Spring Boot项目,只需简单几步即可完成集成:

添加Maven依赖

xml
<dependency> <groupId>cloud.tianai.captcha</groupId> <artifactId>tianai-captcha-springboot-starter</artifactId> <version>1.5.3</version> </dependency>

配置 application.yml

在application.yaml中配置验证码相关配置

yaml
# 滑块验证码配置, 详细请看 cloud.tianai.captcha.autoconfiguration.ImageCaptchaProperties 类 captcha: # 如果项目中使用到了redis,滑块验证码会自动把验证码数据存到redis中, 这里配置redis的key的前缀,默认是captcha:slider prefix: captcha # 验证码过期时间,默认是2分钟,单位毫秒, 可以根据自身业务进行调整 expire: # 默认缓存时间 2分钟 default: 10000 # 针对 点选验证码 过期时间设置为 2分钟, 因为点选验证码验证比较慢,把过期时间调整大一些 WORD_IMAGE_CLICK: 20000 # 使用加载系统自带的资源, 默认是 false(这里系统的默认资源包含 滑动验证码模板/旋转验证码模板,如果想使用系统的模板,这里设置为true) init-default-resource: true # 缓存控制, 默认为false不开启 local-cache-enabled: false # 缓存开启后,验证码会提前缓存一些生成好的验证数据, 默认是20 local-cache-size: 20 # 缓存开启后,缓存拉取失败后等待时间 默认是 5秒钟 local-cache-wait-time: 5000 # 缓存开启后,缓存检查间隔 默认是2秒钟 local-cache-period: 2000 # 配置字体包,供文字点选验证码使用,可以配置多个,不配置使用默认的字体 font-path: - classpath:font/SimHei.ttf secondary: # 二次验证, 默认false 不开启 enabled: false # 二次验证过期时间, 默认 2分钟 expire: 120000 # 二次验证缓存key前缀,默认是 captcha:secondary keyPrefix: "captcha:secondary"

生成和验证验证码

使用 ImageCaptchaApplication 生成验证码数据对象

java
@RestController public class TestController { @Autowired private ImageCaptchaApplication application; @GetMapping("/genCaptcha") public void genCaptcha() { // 1.生成验证码(该数据返回给前端用于展示验证码数据) // 参数1为具体的验证码类型, 默认支持 SLIDER、ROTATE、WORD_IMAGE_CLICK、CONCAT 等验证码类型,详见: `CaptchaTypeConstant`类 return application.generateCaptcha(CaptchaTypeConstant.SLIDER); } }

验证码数据验证

使用 ImageCaptchaApplication 校验客户端提交的验证码数据

java
@RestController public class TestController { @Autowired private ImageCaptchaApplication application; @PostMapping("/check") public ApiResponse<?> checkCaptcha(@RequestBody Data data) { ApiResponse<?> response = imageCaptchaApplication.matching(data.getId(), data.getData()); if (response.isSuccess()) { // 验证码验证成功,此处应该进行自定义业务处理, 或者返回验证token进行二次验证等。 return ApiResponse.ofSuccess(Collections.singletonMap("validToken", data.getId())); } return response; } @lombok.Data public static class Data { // 验证码id private String id; // 验证码数据 private ImageCaptchaTrack data; // 可以加用户自定义业务参数... } }

高级功能与自定义配置

自定义验证码资源

通过扩展ResourceStore接口添加自定义背景图片

添加模板使用 addTemplate(type1, template1) 方法, type1: 验证码类型, template1: 验证码模板相关数据

添加背景图片使用 addResource(type1, res1)方法, type1: 验证码类型, res1: 验证码背景图片数据

java
@Component @RequiredArgsConstructor public class CaptchaResourceConfiguration { private final CrudResourceStore resourceStore; @PostConstruct public void init() { // 滑块验证码 模板 (系统内置) ,这里添加的模板等同于 captcha.init-default-resource=true , 如果配置中设置了加载默认模板,这里模板可不用配置 ResourceMap template1 = new ResourceMap("default", 4); template1.put("active.png", new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/active.png"))); template1.put("fixed.png", new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/fixed.png"))); ResourceMap template2 = new ResourceMap("default", 4); template2.put("active.png", new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/active.png"))); template2.put("fixed.png", new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/fixed.png"))); // 旋转验证码 模板 (系统内置) ResourceMap template3 = new ResourceMap("default", 4); template3.put("active.png", new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/active.png"))); template3.put("fixed.png", new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/fixed.png"))); // 1. 添加一些模板 addTemplate(CaptchaTypeConstant.SLIDER, template1); addTemplate(CaptchaTypeConstant.SLIDER, template2); addTemplate(CaptchaTypeConstant.ROTATE, template3); // 2. 添加自定义背景图片, resource 的参数1为资源类型(默认支持 classpath/file/url ), resource 的参数2为资源路径, resource 的参数3为标签 resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/a.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/b.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/c.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/d.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/e.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/g.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/h.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/i.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/j.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.ROTATE, new Resource("classpath", "bgimages/48.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.CONCAT, new Resource("classpath", "bgimages/48.jpg", "default")); resourceStore.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource("classpath", "bgimages/c.jpg", "default")); } }

二次验证增强安全

对于高安全场景,可以开启二次验证,如果设置配置文件 captcha.secondary.enabled=true 时开启了二次验证

java
@RestController public class TestController { @Autowired private ImageCaptchaApplication sca; @RestController public class TestController { @Autowired private ImageCaptchaApplication application; @PostMapping("/login") public void genCaptcha(@RequestParam String validToken) { // 1.生成验证码(该数据返回给前端用于展示验证码数据) // 参数1为具体的验证码类型, 默认支持 SLIDER、ROTATE、WORD_IMAGE_CLICK、CONCAT 等验证码类型,详见: `CaptchaTypeConstant`类 boolean valid = ((SecondaryVerificationApplication) application).secondaryVerification(id); if (valid) { // 验证码验证成功,此处进行自定义业务处理 } throw new RuntimeException("验证码验证失败"); } } }

性能调优建议

  • 生产环境建议配置Redis集群存储验证数据,提升并发性能

  • 图片资源建议使用CDN加速加载,提升用户体验

  • 缓存配置根据业务量调整本地缓存大小,默认20个验证码

注意事项

环境要求

  • JDK 1.8+ 环境运行最佳

  • Spring Boot 2.x 完全兼容

  • Redis(可选,生产环境推荐)

安全实践

  • 定期更新背景图资源,建议每周更新,防止图库攻击

  • 开启IP频率限制,建议10次/分钟,防止暴力攻击

  • 禁止前端直接返回校验原始数据,确保数据安全

移动端适配

  • 验证区域不小于300×150px,确保触摸精度

  • 调整触摸事件采样频率,优化移动端体验

  • 使用响应式布局方案,适配不同屏幕尺寸

总结

tianai-captcha 作为一款开源行为验证码工具,成功解决了传统验证码在安全性、用户体验和开发效率之间的平衡问题。通过简单集成,开发者可以快速为系统添加多种炫酷且安全的行为验证码,有效防御机器攻击的同时提升用户满意度。

无论是创业项目还是企业级应用,tianai-captcha 都能提供可靠的验证码解决方案,让开发者专注于核心业务,而不必在验证码模块投入过多开发维护成本。

本文作者:柳始恭

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!