go-qrcode仅生成静态二维码图片,动态跳转需配合后端路由(如/go/{shortid})、shortid映射存储(redis/db)、目标url白名单校验及安全重定向逻辑,缺一不可。

Go-qrcode 生成带参数的动态跳转二维码,关键在 URL 编码和 HTTP 重定向逻辑
直接用 qrcode.Encode 生成静态图片没用——动态跳转码必须让扫码后访问一个你可控的路由,由该路由解析参数并执行重定向。Go-qrcode 只负责“画图”,跳转逻辑得你自己写。
常见错误是把完整跳转 URL(比如 https://example.com/go?to=https%3A%2F%2Ftarget.com%2Fabc)直接喂给 qrcode.Encode,结果二维码能扫,但服务端没配对应路由,或没做 URL 解码,导致跳转失败、404 或跳到错误地址。
- 动态跳转码 = 二维码图片 + 后端跳转路由(如
/go)+ 安全参数解析 -
qrcode.Encode的输入必须是纯字节数据,传入的 URL 字符串需确保已正确编码(特别是to参数值) - 别在二维码里硬编码敏感目标地址;应使用短 ID 映射(见下节),否则无法撤回、审计或限流
用 shortID 替代明文 URL,避免二维码内容泄露和跳转失控
把真实跳转地址存进 map / Redis / DB,二维码只编码一个随机 shortID(如 "a7f2x"),扫码请求先查 shortID 对应的目标 URL,再 302 跳转。这样既能换目标地址,也能加统计、限速、过期逻辑。
示例流程:
1. 用户请求 /qrcode?to=https://pay.example.com/order?id=123
2. 服务端生成 shortID "b8m9q",存入 Redis:SET q:b8m9q https://pay.example.com/order?id=123 EX 3600
3. 调用 qrcode.Encode("https://your.app/go/b8m9q", qrcode.Low, 256)
4. 扫码访问 /go/b8m9q → 查 Redis → 302 到目标地址
- shortID 建议用
crypto/rand生成 5–6 位 base62 字符,避免可预测性 - Redis key 加前缀(如
q:)防止命名冲突;设置 TTL 防止垃圾数据堆积 - 不要用整数自增 ID(如
/go/123),容易被枚举、撞库
HTTP 路由处理 /go/{shortID} 时必须校验和清理目标 URL
从存储中取出目标 URL 后不能直接 http.Redirect —— 攻击者可能篡改 shortID 指向恶意域名,或注入 open redirect 漏洞。必须做白名单校验和 scheme 清理。
- 只允许
https?协议,拒绝javascript:、data:、file:等危险 scheme - 用
url.Parse解析目标地址,检查Host是否在可信域名列表内(如[]string{"pay.example.com", "blog.example.com"}) - 丢弃所有非 ASCII 字符、控制字符;对 path 和 query 做
url.PathEscape/url.QueryEscape再拼接(如果需二次构造) - 若校验失败,返回 400 或 404,**不要**重定向到首页或默认页(这会放大 open redirect 风险)
生成 PNG 时注意 Content-Type 和缓存头,避免前端加载失败
Go-qrcode 默认输出 []byte,但直接 w.Write() 不设 header,浏览器可能当文本渲染或触发下载。PNG 还要控制缓存——动态码不该被 CDN 或浏览器长期缓存。
- 务必设置
w.Header().Set("Content-Type", "image/png") - 加
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate"),防止旧二维码扫出过期跳转 - 如果用
qrcode.Write直接写入http.ResponseWriter,它内部不设 header,仍需手动补全 - 别用
log.Printf打印二维码二进制——会乱码且阻塞响应,调试用os.WriteFile("debug.png", data, 0644)更安全
真正难的不是画码,是让每次扫码都落到你预期的跳转路径上,且不被绕过、不被滥用。shortID 映射、URL 校验、响应头控制,这三个点漏掉任一个,动态码就等于裸奔。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











