🌏 Looking for English? Read the English README · Online docs: English Documentation
中文文档 · 在线文档
-
tianai-captcha 目前支持的行为验证码类型
- 滑块验证码(
SLIDER) - 旋转验证码(
ROTATE) - 滑动还原验证码(
CONCAT) - 文字点选验证码(
WORD_IMAGE_CLICK) - 工作量证明验证码(
POW,v1.5.6 新增,无图片、前端自动求解) - 后面会陆续支持市面上更多好玩的验证码玩法... 敬请期待
- 滑块验证码(
-
完整可运行示例:tianai-captcha-demo
-
更详细的配置说明请看 在线文档
当前版本:1.5.6
-
导入依赖
<dependency> <groupId>cloud.tianai.captcha</groupId> <artifactId>tianai-captcha-springboot-starter</artifactId> <version>1.5.6</version> </dependency>
-
最小配置(
application.yaml)captcha: # 加载系统自带滑块/旋转等模板 init-default-resource: true expire: default: 10000 WORD_IMAGE_CLICK: 60000 POW: 60000
-
使用
ImageCaptchaApplication生成和校验验证码@RestController public class CaptchaController { @Autowired private ImageCaptchaApplication application; /** 生成验证码,type 可选:SLIDER / ROTATE / CONCAT / WORD_IMAGE_CLICK / POW */ @RequestMapping("/gen") public ApiResponse<ImageCaptchaVO> gen(@RequestParam(value = "type", required = false) String type) { if (type == null || type.isEmpty()) { type = CaptchaTypeConstant.SLIDER; } return application.generateCaptcha(type); } /** 校验验证码,data 为前端回传的轨迹 / POW 结果 */ @PostMapping("/check") public ApiResponse<?> check(@RequestBody CaptchaData data) { ApiResponse<?> match = application.matching(data.getId(), data.getData()); if (match.isSuccess()) { // 成功后把 id 回给前端,可用于二次验证 / 业务绑定 return ApiResponse.ofSuccess(Collections.singletonMap("id", data.getId())); } return match; } @lombok.Data public static class CaptchaData { private String id; private ImageCaptchaTrack data; } }
-
SpringBoot 配置文件说明(常用项)
# 详细请看 cloud.tianai.captcha.spring.autoconfiguration.SpringImageCaptchaProperties captcha: # Redis key 前缀,默认 captcha(引入 spring-boot-starter-data-redis 后会自动用 Redis 存校验数据) prefix: captcha # 过期时间,单位毫秒;未配 default 时内置默认约 20 秒 expire: default: 10000 WORD_IMAGE_CLICK: 60000 POW: 60000 # 是否加载系统自带模板,默认 false init-default-resource: true # 本地预生成缓存,默认 false local-cache-enabled: true local-cache-size: 20 local-cache-wait-time: 1000 local-cache-period: 5000 # 点选验证码字体,可配置多个,支持 ?tag=xxx font-path: - classpath:font/simhei.ttf secondary: # 二次验证,默认 false enabled: false expire: 120000 keyPrefix: "captcha:secondary"
-
自定义背景图(推荐)
使用系统模板时,背景图尺寸建议 600x360。
POW不需要背景图。@Configuration public class CaptchaResourceConfiguration { @Bean public ResourceStore resourceStore() { LocalMemoryResourceStore store = new LocalMemoryResourceStore(); store.addResource(CaptchaTypeConstant.SLIDER, new Resource("classpath", "bgimages/a.jpg", "default")); store.addResource(CaptchaTypeConstant.ROTATE, new Resource("classpath", "bgimages/48.jpg", "default")); store.addResource(CaptchaTypeConstant.CONCAT, new Resource("classpath", "bgimages/48.jpg", "default")); store.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource("classpath", "bgimages/c.jpg", "default")); return store; } }
- 导入依赖
<dependency>
<groupId>cloud.tianai.captcha</groupId>
<artifactId>tianai-captcha</artifactId>
<version>1.5.6</version>
</dependency>- 构建
ImageCaptchaApplication
ImageCaptchaApplication application = TACBuilder.builder()
.addDefaultTemplate()
// 背景图宽高建议 600x360;Resource 参数1为 classpath / file / URL
.addResource("SLIDER", new Resource("classpath", "META-INF/cut-image/resource/1.jpg"))
.addResource("WORD_IMAGE_CLICK", new Resource("classpath", "META-INF/cut-image/resource/1.jpg"))
.addResource("ROTATE", new Resource("classpath", "META-INF/cut-image/resource/1.jpg"))
.addResource("CONCAT", new Resource("classpath", "META-INF/cut-image/resource/1.jpg"))
.expire("default", 10000L)
.expire(CaptchaTypeConstant.WORD_IMAGE_CLICK, 60000L)
.build();
// 支持 SLIDER / ROTATE / CONCAT / WORD_IMAGE_CLICK / POW
ApiResponse<ImageCaptchaVO> res = application.generateCaptcha(CaptchaTypeConstant.SLIDER);
// id 与 ImageCaptchaTrack 均由前端回传(此处 track 仅为占位)
ImageCaptchaTrack track = null; // 实际项目中由前端 POST 传入
ApiResponse<?> valid = application.matching(res.getData().getId(), new MatchParam(track));| 条目 | |
|---|---|
| 兼容性 | Chrome、Firefox、Safari、Opera、主流手机浏览器、iOS 及 Android 内嵌 WebView |
| 框架支持 | H5、Angular、React、Vue2、Vue3 |
请保证 前端 SDK 与后端版本一致(1.5.6)。
-
下载 tac 包:tianai-captcha-1.5.6 / tac-web.zip
放到可访问目录(如 SpringBootstatic/tac,或 Vue/React 的public/tac) -
页面引入并初始化
<link rel="stylesheet" href="/tac/css/tac.css">
<script src="/tac/js/tac.min.js"></script>
<div id="captcha-box"></div>
<script>
new TAC({
requestCaptchaDataUrl: "/gen?type=SLIDER",
validCaptchaUrl: "/check",
bindEl: "#captcha-box",
validSuccess: (res, c, tac) => {
tac.destroyWindow();
// 与后端 /check 成功返回一致,业务侧拿 id
console.log("captcha id =", res.data.id);
},
validFail: (res, c, tac) => tac.reloadCaptcha()
}, {
// logoUrl: null // 隐藏 logo
}).init();
</script>首屏只引入很小的 load.js,用户点击登录时再拉取 tac.min.js / tac.css。
- 同样准备好
tac目录 - 下载 load.js(或 load.min.js)
<script src="/js/load.js"></script>
<button id="login-btn">登录</button>
<div id="captcha-box"></div>
<script>
document.getElementById("login-btn").onclick = function () {
const config = {
requestCaptchaDataUrl: "/gen?type=SLIDER",
validCaptchaUrl: "/check",
bindEl: "#captcha-box",
validSuccess: (res, c, tac) => {
tac.destroyWindow();
console.log("验证成功", res.data.id);
},
validFail: (res, c, tac) => tac.reloadCaptcha()
};
const style = {
logoUrl: null, // 隐藏 logo;也可写成 logoUrl: "/xx/logo.png"
};
// 参数1:tac 目录(需包含 js/tac.min.js、css/tac.css)
// window.initTAC 与 window.loadTAC 等价
window.loadTAC("./tac", config, style)
.then(tac => tac.init())
.catch(e => console.log("初始化失败", e));
};
</script>const style = {
btnUrl: "https://minio.tianai.cloud/public/captcha-btn/btn3.png",
bgUrl: "https://minio.tianai.cloud/public/captcha-btn/btn3-bg.jpg",
logoUrl: "https://minio.tianai.cloud/public/static/captcha/images/logo.png",
moveTrackMaskBgColor: "#f7b645",
moveTrackMaskBorderColor: "#ef9c0d",
i18n: {
slider_title: "拖动滑块完成拼图",
pow_title: "正在验证中:",
pow_title_size: "15px"
}
};// 默认难度参数 [4, 16, 4]
application.generateCaptcha(CaptchaTypeConstant.POW);
// 自定义:difficulty / saltLen / count
GenerateParam param = new GenerateParam();
param.setType(CaptchaTypeConstant.POW);
param.addParam(ParamKeyEnum.POW_PARAM, Arrays.asList(4, 16, 4));
application.generateCaptcha(param);前端使用 1.5.6+ SDK,生成接口返回 type: "POW" 即可自动求解提交,无需拖动。


