# 5.3 验证码机制 :::tip 概述 图形验证码由 `utility/captcha` 生成 SVG/PNG dataURL,答案存缓存(TTL 300 秒)且一码一用。登录接口携带 key 时强制校验,配合认证接口限流防爆破。 ::: ## 生命周期 ```text GET /api/captcha(公开接口) → captcha.Generate:随机字符(captcha.length)+ 随机 key → 答案存 cache(CacheKeyCaptcha(key),TTL=captcha.expire) → 返回 { key, captcha: dataURL }(CaptchaRes) POST /api/login 携带 key + code → captcha.Verify:比对答案 → 无论成败删除缓存键(一码一用,防重放) → 登录继续 ``` ## 配置(config.yaml captcha 节) | 键 | 默认 | 说明 | |---|---|---| | expire | 300 | 有效期(秒) | | length | 6 | 字符数(4–8) | | chars | ABCDEFGHJKLMNPQRSTUVWXYZ23456789 | 排除易混淆字符(0O、1lI) | | fontPath | resource/fonts/Vera.ttf | TTF 字体;缺失降级 SVG 渲染 | | imageWidth / imageHeight / fontSize | 160 / 50 / 40 | 尺寸(字符放不下自动加宽) | | noiseLines / noiseDots | 8 / 500 | 干扰线 / 噪点 | | bypassCode | 空 | 万能码:携带该值免校验,**仅开发调试** | :::warning 生产红线 `app.prod=true` 时非空 bypassCode 会被启动校验直接拒绝——万能码绝不能带上线。 ::: ## 前端接入 登录页从 `/api/captcha` 拿 uuid 与图片,提交时回传两者。前端四种登录表单(账密/手机/扫码/注册)中需要验证码的均走同一契约。 ## 渲染实现 优先 TTF 字体渲染 PNG(opentype + golang.org/x/image),字体文件缺失时降级为 SVG 文本渲染——两种格式前端同为 `` 消费,无感知差异。 ## 与其他防护的配合 | 防护 | 层 | |---|---| | 验证码 | 人机校验(一码一用) | | authLimit 限流 | 10 次/分钟/IP(登录/验证码/令牌兑换共享配额) | | 失败日志 | gin_login_log status=1 留痕 | 三层叠加使暴力破解在 IP 与验证两道关卡上都不可行。 ## 下一步 → [5.4 权限管理(RBAC)](/zh/core/rbac.html)