验证码接口必须返回ID和base64图片,ID用于验证定位,base64直接渲染;Verify需校验ID/code非空并全局复用store,点选类须用captcha.Check而非store.Verify。

验证码生成接口必须返回 ID 和 base64 图片
前端要渲染验证码,靠的不是后端返回一张 PNG 文件,而是 idKey + image 字段组合。ID 用于后续验证时定位存储中的答案,base64 图片直接塞进 <img src="data:image/png;base64,..." alt="Go语言Echo框架验证码服务接口" > 即可显示。
常见错误是只返回图片不返回 ID,或把 ID 放在响应头里——前端拿不到,验证时传空 ID 导致 store.Verify(id, code, true) 永远失败。
- 生成时必须调用
captcha.Generate(),它返回三个值:id、b64s、answer -
id要原样透传给前端,不能做任何哈希、截断或加前缀处理 - 开发环境建议用
global.Log.Infof("[CAPTCHA_DEBUG] ID: %s, Code: %s", id, answer)打印答案,方便联调 - 别用
c.JSON(200, map[string]interface{}{"image": b64s})省略 ID 字段
Verify 接口必须严格校验 ID 和 code 参数存在性
store.Verify(id, code, true) 这个调用本身不检查参数是否为空,如果 id 是空字符串或 code 是空,它会直接查空 key,大概率返回 false,但不会报错——前端看到的是“验证码错误”,实际是参数没传过来。
所以 Verify 接口开头必须手动判断:
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
立即学习“go语言免费学习笔记(深入)”;
- 用
c.Query("id")和c.Query("code")获取参数,不能用c.Param(这不是路径参数) - 检查
id == "" || code == "",是则直接返回 400,避免浪费一次存储查询 - 第三个参数设为
true表示验证成功后自动删除该 ID 对应的验证码,防止重放 - 不要在验证通过后还去查一遍数据库或 Redis 确认——
store.Verify已完成全部逻辑
Store 实例必须全局复用,不能每次请求 new 一个
base64Captcha 的 store 是有状态的,比如内存 store 用 sync.Map 存答案,Redis store 用客户端连 Redis。如果在每个 Captcha 或 Verify handler 里都 new 一个 store,那生成和验证就根本不在同一个存储空间里,必然失败。
- 推荐在 main 初始化时创建一次:例如
store := base64Captcha.NewMemoryStore()或store := base64Captcha.NewRedisStore(redisClient) - 把这个
store实例注入到 handler 函数闭包里,或作为全局变量(简单项目)或依赖注入(复杂项目) - 内存 store 仅适合单机调试;生产必须用 Redis store,否则多实例部署时验证码无法跨节点验证
- Redis store 的 key 前缀默认是
captcha:,可通过store.SetKeyPrefix("myapp:captcha:")修改,避免和其他服务冲突
前端传来的 captchaData 必须原样透传给后端验证
点选类验证码(如知识库中提到的 clickCaptcha)生成的 captchaData 是结构化数据,通常包含坐标数组、ID、时间戳等字段。服务端验证时不能只取其中某个字段,也不能 JSON.stringify 后再发——必须保持原始格式。
- 前端调用
adminLogin({loginForm, captcha: captchaData})时,captchaData应作为 JSON body 字段发送,Content-Type 设为application/json - 后端用
c.BindJSON(&req)接收,req.Captcha类型应为map[string]interface{}或自定义结构体 - 验证函数
captcha.Check(req.Captcha, true)的第一个参数就是这个原始结构体,框架内部会提取id和code字段 - 别手动从
captchaData里取id拼成 query string 再 GET 请求——这绕过了 CSRF 防护,也破坏了点选验证码的设计意图
Check 方法和字符型验证码的 store.Verify 不是同一套逻辑,前者需要调用 captcha.Check(...)(来自 base64Captcha 的扩展能力),后者才是纯字符串比对。混用会导致永远验证失败。

















