优先选用成熟库如 github.com/dchest/captcha,其默认启用干扰线和噪点,通过 captcha.generatecaptcha(id, digits) 设置字符数;需中文或特殊字体时须提前 font.register ttf;若需精确控制干扰线,则手动用 image/draw 构建 *image.rgba 并自定义绘制。

用 golang.org/x/image 画验证码图片前先确认替代方案是否更合适
直接手撸图片验证码在 Go 里不是最优解——gocaptcha、captcha(来自 github.com/dchest/captcha)等库已稳定支持干扰线、噪点、扭曲字体,且默认使用内存缓存 + URL 接口,比自己调 image/draw 拼更省心。除非你有特殊字体/布局需求,否则别从零实现绘图逻辑。
github.com/dchest/captcha 怎么启用干扰线和自定义长度
这个库默认就开启干扰线和噪点,但很多人没注意到它不生成“图片二进制”,而是返回 base64 编码的 PNG 数据或直接写入 http.ResponseWriter。关键参数藏在初始化时:
-
captcha.GenerateCaptcha(id, digits)中digits控制字符数(如5),不是随机字符串长度 - 干扰线强度由底层
capchagen包控制,无法直接调参;但可通过captcha.SetCustomStore替换存储后,在生成前调用captcha.NewImage手动干预(见下一点) - 若需中文或特殊字体,得提前用
font.Register注册 ttf 文件,否则 fallback 到内置位图字体(无抗锯齿,看起来像马赛克)
想完全控制干扰线?绕过默认生成器,用 image + draw 手绘
当你需要精确控制线条密度、角度、颜色渐变,或者叠加多层干扰(比如先画斜线再画波浪线),就得放弃 captcha 的封装,自己构建 *image.RGBA:
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 创建画布:
img := image.NewRGBA(image.Rect(0, 0, 120, 40)),宽高建议 ≥100×40,太小会导致文字挤在一起 - 填背景色:
draw.Draw(img, img.Bounds(), &image.Uniform{color.RGBA{240, 240, 240, 255}}, image.Point{}, draw.Src) - 画干扰线:循环调用
draw.Line,起点终点用rand.Float64()随机,颜色设为浅灰(如color.RGBA{200, 200, 200, 180}),alpha 值别设 255,否则盖住文字 - 写字:用
font.Face和golang.org/x/image/font/basicfont或自定义 ttf,配合text.Draw;注意 y 坐标要加 font.Metrics().Height,否则字被截顶
HTTP 输出时 Content-Type 和缓存头容易漏设
生成完 *image.RGBA 后,用 png.Encode(w, img) 写响应体,但常有人忘记:
- 必须设置
w.Header().Set("Content-Type", "image/png"),否则浏览器当文本渲染,显示乱码 - 验证码应禁用 CDN 和代理缓存:
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0") - ID 和图片要绑定存储(如
map[string]string+sync.RWMutex),且验证后立即删除,避免重放攻击
干扰线本身不防 OCR,真正起作用的是字符扭曲+背景融合+有限有效期;过度堆砌干扰反而降低可读性,让真实用户反复刷新。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










