Revel 框架需用 Go 原生图像库实现验证码,推荐 image/draw+image/png;验证码控制器须生成随机字符串、绘制干扰线、设置无缓存头并存入 Redis;校验时需严格大小写匹配且立即删除 key。

Revel 框架本身不内置图形验证码功能,也没有官方 Captcha 组件。想在 Revel 项目中加验证码,得自己集成——但不用从零画图,关键在于选对轻量、可控、易嵌入的方案。
Revel 中用 Pillow(Python)或 GD(PHP)?不对,Revel 是 Go 框架
Revel 是 Go 语言框架,所有逻辑必须用 Go 实现。别被其他语言的验证码库误导。常见错误是:
- 试图在
Revel里调用 PHP 的imagecreate()或 Python 的PIL.Image—— 根本不可行; - 直接搬运 Java Servlet 的
VerifyImgServlet代码,忽略 Go 的 HTTP 处理模型和内存管理差异。
正确做法是:用 Go 原生图像库生成 PNG/JPEG,配合 Revel 的控制器生命周期控制输出。推荐使用标准库 image + image/draw + image/png,辅以 golang.org/x/image/font(如需真字体渲染)。
怎么写一个可直接挂到 Revel 路由的验证码控制器
你需要一个返回 image/png 的 Action,并把验证码文本存进会话(session)或 Redis(集群必备)。示例结构如下:
- 在
app/controllers下新建captcha.go - 定义
Captcha.Get()方法,做三件事:- 生成 4 位随机字符串(避开
0/O/1/l/I) - 创建
*image.RGBA画布,绘制字符+简单干扰线(别加噪点或扭曲——Go 生态缺乏成熟抗 OCR 工具,过度干扰反而伤体验) - 设置响应头
Content-Type: image/png,用png.Encode()写入c.Response.Out
- 生成 4 位随机字符串(避开
Revel 的会话默认走加密 Cookie,适合单机开发;但上线前必须切到 Redis(通过 revel.Harness.Config.Set("session.store", "redis")),否则集群下验证码校验必失败。
验证码存储和校验容易漏掉的关键点
-
Revel的c.Session.Set("captcha", code)不会自动设置过期时间,必须手动搭配time.Now().Add(5 * time.Minute)存 Redis; - 前端请求验证码图片时,
img src="/captcha/get"可能被浏览器缓存,导致多次提交用同一个码 —— 必须在控制器里加:c.Response.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0"); - 校验时别只比对字符串,要严格区分大小写(除非业务明确允许),且验证成功后立刻删除 Redis 中的 key,防止重放;
- 若用自定义字体(如
DejaVuSans.ttf),确保生产环境 Linux 容器里已安装该字体文件,并用truetype.Parse()加载——本地能跑不等于线上能跑。
Revel 的验证码不是“加个组件就完事”,它卡在三个真实断点上:Go 图像绘制的精细度控制、会话存储从 Cookie 切 Redis 的时机、以及前端 img 缓存与后端状态同步的时序。这三个地方任一出错,用户就会看到空白图、反复输错、或验证码永远不刷新。


















