Base64Captcha高性能依赖store选型、driver配置和校验链路控制:DefaultMemStore无并发锁与过期清理,高并发下内存暴涨;DriverString需显式设全参数防panic;VerifyString不处理空格/大小写/过期,须前置清洗与Redis原子读删。

直接用 github.com/mojocn/base64Captcha 就能跑通高性能验证码,但“高性能”不等于“默认就高”,关键在 store 选型、driver 配置和校验链路的控制点——漏掉任一环节,QPS 上去后不是内存爆掉就是验证全失败。
为什么 DefaultMemStore 在生产环境会吃光内存
它用 map[string]string 存 ID → answer,没有并发锁,也没有过期清理逻辑。TTL 固定 10 分钟,但 key 永远不删,高并发下几分钟就能占满几百 MB 内存。
- 别写
base64Captcha.DefaultMemStore上生产,哪怕只跑单实例 - 必须自己实现
base64Captcha.Store接口,重点是Set(id, answer, expire)和Get(id, clear bool) - Redis 实现时,
Set要用SET key value EX 300(5 分钟),Get必须返回answer string, ok bool,且clear=true时得调DEL key - 如果用本地缓存(如
freecache),注意加sync.RWMutex,否则多 goroutine 写 map 会 panic
DriverString 初始化必须显式指定全部参数
NewDriverString 看似简单,但少一个参数就会 panic 或生成空白图——它不接受零值默认,也不会降级。
- 宽高必须设,比如
80, 24,太小(如 60×20)OCR 识别率飙升,太大(如 200×60)前端缩放失真 -
Length建议 4–5,6 位以上用户输入错误率明显上升;NoiseCount控制干扰线数量,设为 0 会降低安全性 -
Source别用默认大写字母,易混淆O/0、I/1,推荐"23456789ABCDEFGHJKLMNPQRSTUVWXYZ" - 字体路径不生效?不是配置问题,是
DriverString不支持自定义字体——要用中文或特殊字体,必须换DriverChinese并预加载.ttf文件
VerifyString 返回 false 的真实原因往往不是代码逻辑
base64Captcha.VerifyString 只做字符串比对,它不查过期、不 trim 空格、不转大小写。返回 false 时,90% 是数据没对齐。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 前端传来的
id带空格或换行?校验前先strings.TrimSpace(id) - 用户输入
Ab3x,但 Redis 里存的是ab3x?要么初始化 config 时设CaseSensitive: false,要么统一转小写再比 -
store.Get(id, true)必须调用,第二个参数true表示取完即删,防重放;漏掉这步,同一 ID 可被反复验证 - Redis key 已过期但没删干净?
GET captcha:xxx返回 nil,VerifyString就拿空字符串比对,必然 false
base64 图片编码不能用 URLEncoding
前端 <img src="data:image/png;base64,..."> 要求标准 base64 编码,URLEncoding 会把 + 和 / 替换成 - 和 _,导致图片无法渲染。
- 生成时必须用
base64.StdEncoding.EncodeToString(buf.Bytes()) - 别在 buffer 上反复调
String(),它每次都会新分配内存;用Bytes()直接取 slice - 如果自己手动生成 PNG(不推荐),
image/png.Encode第二个参数必须是*bytes.Buffer,传strings.Builder会 panic
真正卡住性能的从来不是图像生成,而是 store 的读写延迟和并发安全。ID 查不到、答案比对错、base64 解码失败——这些问题在压测时集中爆发,但根源都在初始化那几行配置里。


















