Iris无内置验证码功能,所谓iris.Captcha是误解;须用base64Captcha等第三方库手动集成,显式注册路由、设置Content-Type、禁用gzip及JSON中间件,否则返回空图或404。

用 iris.Captcha 生成图片验证码时为什么返回空图或 404?
因为 Iris 官方并未内置 Captcha 功能,iris.Captcha 并不存在 —— 这是常见误解。实际需借助第三方库(如 github.com/mojocn/base64Captcha)手动集成,且必须显式注册路由、设置响应头、避免中间件拦截二进制输出。
实操建议:
- 不要尝试调用
iris.Captcha或查找 Iris 内置 captcha 方法,它不存在 - 用
base64Captcha生成*captcha.Captcha实例后,必须调用.WriteTo()直接写入context.ResponseWriter(),不能走ctx.JSON()或ctx.Text() - 确保路由 handler 中未启用自动 JSON 封装(如全局
iris.JSONmiddleware),否则二进制数据会被强制转成 JSON 字符串导致乱码 - 响应头需显式设为
Content-Type: image/png(PNG 是默认格式,若改用 JPEG 需同步改 header 和 WriteTo 参数)
如何在 Iris 中完成验证码生成 + ID 返回的完整响应?
典型需求是:前端请求 /captcha,后端返回图片 + 一个唯一 captchaID(用于后续校验)。这需要两步分离:生成时存 ID-答案对,响应时把 ID 嵌入 JSON 或 HTTP header。
实操建议:
- 用
base64Captcha.GenerateCaptcha()得到id, capt, err,其中capt是验证码对象,含答案和图像数据 - 将
id和capt.Solve(明文答案)存入内存 map / Redis,过期时间建议 5 分钟(time.Now().Add(5 * time.Minute)) - 响应时先写图片:
capt.WriteTo(ctx.ResponseWriter()),再单独返回 ID —— 但注意:HTTP 不允许一个响应发两次 body,所以必须选其一:
→ 方案 A:图片走独立路由(如/captcha/image/:id),ID 从另一接口(如/captcha/new)返回 JSON;
→ 方案 B:图片用 base64 编码塞进 JSON(适合小图,但增加约 33% 体积,且移动端可能触发缓存策略问题) - 推荐方案 A,更符合 REST 语义,也利于浏览器缓存图片
校验用户提交的验证码时,base64Captcha.VerifyCaptcha 总是返回 false?
常见原因不是逻辑错,而是数据没对齐:后端比对的是存储时的原始答案(如 "Ab2x"),而用户输入常带空格、大小写误判、全角字符,或前端未正确传参。
实操建议:
- 存储答案时统一转小写并 TrimSpace:
strings.ToLower(strings.TrimSpace(capt.Solve)) - 校验前对用户输入做同样处理:
strings.ToLower(strings.TrimSpace(input)) - 确认传入
VerifyCaptcha(id, input)的id确实是生成时返回的那个字符串(注意 URL decode,比如%3D要还原) - 检查存储结构是否线程安全:Iris 默认多 goroutine 并发,若用
map[string]string存验证码,必须加sync.RWMutex,否则高并发下可能 panic 或读到空值 - Redis 方案更稳妥,用
SET key value EX 300直接带过期,校验即GETDEL(防止重放)
Iris 中验证码路由被 gzip 中间件破坏图片内容怎么办?
启用 iris.Gzip 后,PNG 图片响应体被压缩,但浏览器无法解压二进制图片流,表现为损坏、黑块或直接下载文件。
实操建议:
- 禁止对验证码路由启用 gzip:在注册路由时绕过中间件,例如用
app.Get("/captcha/{id:string}", captchaHandler),而非挂载在带Gzip的子路由器下 - 或在 handler 开头手动禁用:
ctx.ResponseWriter().Header().Set("Content-Encoding", ""),但这不保险,因某些 gzip middleware 会强制重写 - 更可靠做法是:用
app.None()注册该路由(跳过所有默认中间件),再显式添加必要中间件(如日志、超时),排除 gzip - 验证方式:用 curl 检查响应头是否有
Content-Encoding: gzip,以及响应体是否以\x1f\x8b(gzip magic bytes)开头
真正麻烦的不是生成图片,而是 ID 生命周期管理、并发安全、大小写归一化、以及中间件对二进制响应的隐式干扰——这些点漏掉任何一个,都会让验证码看起来“时灵时不灵”。











