☰
think-svg-captcha 使用指南:在 ThinkJS 应用中生成与校验 SVG 验证码
2026/10/15 3:39:35 网站建设 项目流程
  • 后端
  • Web框架

【免费下载链接】thinkjs

Use full ES2015+ features to develop Node.js applications, Support TypeScript.

项目地址:https://gitcode.com/gh_mirrors/thi/thinkjs
点击查看免费下载

think-svg-captcha 是 ThinkJS 生态中基于svg-captcha封装的 SVG 验证码生成组件,核心价值在于将底层 SVG 验证码能力无缝接入 ThinkJS 3.x 应用:开箱即用的默认参数、一行代码生成验证码、自动处理自定义字体加载与缓存。读完本文,你将掌握该组件的默认配置项含义、create()与svgCaptcha(text)两个核心 API 的用法、字体加载与缓存原理,并能结合 ThinkJS 的 Controller、Session 在真实项目中完成验证码的生成与校验闭环。

组件定位:think-svg-captcha 是什么

根据 packages/think-svg-captcha/README.md 的说明,think-svg-captcha是svg-captcha的一个封装(wrap)。它并不重复实现 SVG 绘制逻辑,而是把底层库的能力整理成面向 ThinkJS 开发者友好的接口:

  • 提供一份合理的默认配置(随机串长度、干扰线数量、尺寸、字号、字符集等);
  • 提供ThinkSvgCaptcha类,通过new实例化后即可调用;
  • 在构造阶段完成选项合并与字体加载/缓存,屏蔽底层svg-captcha的全局选项操作细节。

从 packages/think-awesome/README.md 的生态列表中可以看到,该组件的定位就是 "Generate svg captcha",属于 ThinkJS 社区官方维护的功能型中间件/工具包之一。

安装与运行环境

在 ThinkJS 项目中安装该组件:

npm install think-svg-captcha # 或使用 pnpm(当前仓库使用 pnpm workspace 管理) pnpm add think-svg-captcha

根据 packages/think-svg-captcha/package.json 的声明,组件版本为1.0.4,运行时依赖如下:

  • svg-captcha(~1.3.4):底层 SVG 验证码生成库;
  • think-helper(^1.1.3):ThinkJS 通用工具库,用于选项深合并。

同时要求Node.js >= 20.19.0(与 ThinkJS 4.x 的运行环境要求一致)。组件入口为index.js,使用 CommonJS 的module.exports导出,因此既支持require('think-svg-captcha'),也支持 ES Module 的import语法。

默认配置参数详解

组件在 packages/think-svg-captcha/index.js 中内置了一份默认配置,README 中同样给出了完整示例。下表逐项说明每个参数的作用:

参数默认值含义建议取值
size4随机验证码字符串的长度正整数,通常 4~6,越长越难被机器猜测
ignoreChars''需要过滤掉的字符(如易混淆的0O、1lI)传入字符串,例如'0oO1lI'
noise3干扰线数量非负整数,0表示无干扰线
colorfalse是否彩色输出默认灰色;当设置了background时建议设为true
background'#ffffff'SVG 图片背景色十六进制颜色值
width150验证码图片宽度(px)正整数,按展示区域调整
height50验证码图片高度(px)正整数,按展示区域调整
fontPath''自定义字体文件路径源码默认值为空字符串;README 中示例为'./fonts/Comismsh.ttf'
fontSize32验证码文字字号正整数,需小于height
charPreset'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'随机字符的候选字符集任意字符串,字符越多随机性越强

注意一处细节差异:README 展示的默认配置中fontPath为'./fonts/Comismsh.ttf'(演示自定义字体写法),而源码 index.js 中实际默认值为''(即不加载自定义字体,使用svg-captcha内置字体)。以源码实现为准:不传fontPath时组件正常工作,传了才触发字体加载逻辑。

快速上手:两行代码生成验证码

README 给出的最小 demo 如下:

import ThinkSvgCaptcha from 'think-svg-captcha'; let captcha = new ThinkSvgCaptcha(options); captcha.create(); // 返回对象:{data: 'svg path data', text: 'captcha text'} captcha.svgCaptcha(text); // 根据指定 text 生成一个 svg 验证码

这里options可省略(使用默认配置),也可部分传入——组件会把你的选项与默认配置做深合并,未指定的字段自动沿用默认值。

两个 API 的返回值与用途不同:

  • create():随机生成一个验证码,返回{ data, text }。data是 SVG 的 path 数据(可直接嵌入<svg>标签或作为图片响应返回),text是本次生成的明文验证码,通常需要存入 Session 用于后续校验。
  • svgCaptcha(text):按指定文本生成 SVG 验证码,适用于服务端已经确定验证码内容(例如从 Session 读取后重绘)的场景。

测试用例 packages/think-svg-captcha/test/index.js 直接验证了这两个方法的基础调用:

let captcha = new ThinkCaptcha(); let out1 = captcha.create(); let out2 = captcha.svgCaptcha('test');

源码剖析:组件是如何工作的

选项深合并

构造函数首先通过think-helper的extend方法合并默认选项与用户选项(index.js):

this.options = helper.extend({}, defaultOptions, options); this.options.charPreset && (svgCaptcha.options.charPreset = this.options.charPreset);

其中helper.extend在 packages/think-helper/index.js 中定义为require('lodash.merge'),即lodash 深合并——嵌套对象不会出现浅覆盖。合并后,如果用户指定了charPreset,组件会同步写入svg-captcha的全局options.charPreset,从而影响底层随机字符的抽取范围。

自定义字体加载与缓存

当传入fontPath时,构造函数执行字体加载逻辑(index.js):

if (this.options.fontPath) { const theCacheFont = cacheFont[this.options.fontPath]; if (theCacheFont) { this.options.font = theCacheFont; } else { svgCaptcha.loadFont(this.options.fontPath); cacheFont[this.options.fontPath] = svgCaptcha.options.font; } }

组件维护了模块级字体缓存cacheFont(index.js),以fontPath为 key:

  • 首次加载某字体时,调用svgCaptcha.loadFont(fontPath)后把底层解析出的字体对象存入缓存;
  • 之后再次以相同fontPath实例化时,直接复用缓存,避免重复解析字体文件带来的开销。

测试用例中的第三个用例(test/index.js)“with same fontPath”正是对这一缓存路径的回归验证。

核心方法实现

  • create()(index.js):透传合并后的完整选项调用svgCaptcha.create(this.options);
  • svgCaptcha(text)(index.js):透传文本与选项调用svgCaptcha(text, this.options)。

可以看到组件的设计哲学是薄封装:把"默认配置 + 选项合并 + 字体缓存"这些重复性工作收敛到构造阶段,业务侧只需关注生成与校验逻辑。此外,组件在 codecov.yml 中被单独登记为覆盖率统计组件,说明它作为独立模块接受 CI 质量监控。

实战:在 ThinkJS Controller 中完成验证码校验闭环

下面给出在 ThinkJS 3.x/4.x 应用中的典型集成思路(代码为基于组件 API 的示意写法,非仓库内现成文件):

1. 生成验证码接口(写入 Session):

// src/controller/captcha.js import ThinkSvgCaptcha from 'think-svg-captcha'; export default class extends think.Controller { async indexAction() { const captcha = new ThinkSvgCaptcha({ size: 4, noise: 3, color: true, background: '#f4f4f4', width: 150, height: 50, fontSize: 32 }); const { data, text } = captcha.create(); // 将明文存入 session,供登录/注册等接口校验 await this.session('captcha', text.toLowerCase()); // 将 SVG 内容作为 image/svg+xml 返回 this.type = 'image/svg+xml'; this.body = data; } }

2. 校验验证码(在目标业务 Logic 或 Controller 中):

const input = (this.post('captcha') || '').toLowerCase(); const sessionCaptcha = (await this.session('captcha') || '').toLowerCase(); if (!sessionCaptcha || input !== sessionCaptcha) { return this.fail('验证码错误'); }

核心要点:验证码明文只能存服务端 Session,绝不可下发到前端;校验通过后建议立即清除 Session 中的验证码,防止重放攻击;svgCaptcha(text)方法可用于需要"回显指定验证码"的场景(例如刷新时沿用同一文本)。

自定义字体与常见配置示例

若需要使用业务品牌字体,将字体文件放入项目(如www/static/fonts/),然后传入绝对路径或相对路径:

const captcha = new ThinkSvgCaptcha({ fontPath: 'www/static/fonts/Comismsh.ttf', // 相对项目根目录 size: 5, ignoreChars: '0oO1lI', // 过滤易混淆字符,降低用户输错率 noise: 5, // 增加干扰线 charPreset: 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789' });

仓库测试中使用ff2.woff字体验证字体加载路径,该字体文件位于 packages/think-svg-captcha/test/ff2.woff,可作字体加载的参考样例。注意svg-captcha对字体文件格式(ttf/woff 等)有自身要求,实际使用请以该库支持范围为准。

质量验证:如何运行组件测试

组件自带测试脚本(package.json),覆盖三种场景:默认配置生成、自定义fontPath生成、相同fontPath复用缓存。在仓库根目录执行:

# 进入组件目录后运行 pnpm test # 生成覆盖率报告 pnpm coverage

测试使用 Node 内置的node:test运行器(--test --test-concurrency=1),无需额外测试框架,这也符合 ThinkJS 4.x 仓库统一的测试规范。

注意事项与限制

  • 默认字体依赖:不传fontPath时使用svg-captcha内置字体;中文等复杂字形不在默认字符集内,如需中文验证码请自行提供含中文的字体文件并调整charPreset;
  • 字符集与随机性:charPreset字符越少,同长度下可组合空间越小,建议保留大小写字母与数字的组合,并通过ignoreChars排除易混淆字符;
  • color与background联动:按 README 说明,设置背景色后建议将color置为true,否则默认灰阶文字在彩色背景上可能对比度不足;
  • Node 版本:组件声明engines.node >= 20.19.0,部署环境需满足该版本要求。

总结

think-svg-captcha 以极薄的封装成本为 ThinkJS 应用提供了完整的 SVG 验证码能力:默认配置开箱即用,create()与svgCaptcha(text)两个 API 覆盖随机生成与指定文本两种场景,构造阶段的选项深合并与字体缓存则保证了多实例下的稳定与高效。配合 Session 存储明文、前端仅接收 SVG 图形数据的标准做法,即可在登录、注册、评论等防机器人场景中快速落地一套可用的验证码机制。

  • 后端
  • Web框架

【免费下载链接】thinkjs

Use full ES2015+ features to develop Node.js applications, Support TypeScript.

项目地址:https://gitcode.com/gh_mirrors/thi/thinkjs
点击查看免费下载

相关推荐

上一篇:OpenHuman MCP 模块深度解析:静态 TOML 服务器注册表、双传输客户端与 openhuman mcp 服务器
下一篇:JAX DLPack 互操作指南:通过 `jax.dlpack` 实现跨框架零拷贝数据交换

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询