信息发布→ 登录 注册 退出

如何在Golang中实现基础验证码功能_Golang随机生成与验证逻辑实践

发布时间:2026-01-04

点击量:
Go语言需用crypto/rand生成安全验证码,避免rand.Intn();字符集应剔除易混淆字符,配合显式随机读取实现4–6位字母数字组合。

Go 语言本身不内置图形验证码(CAPTCHA)生成能力,但用标准库就能实现轻量、无依赖的字符型验证码——关键是控制好随机性、存储和时效性。

rand 生成安全的 4–6 位字母数字组合

别用 rand.Intn() 直接拼字符串,它默认基于非加密种子,容易被预测。必须显式调用 rand.Read() 配合 crypto/rand

import (
    "crypto/rand"
    "math/big"
)

func generateCode(length int) string {
    const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" // 去掉易混淆字符
    var code []byte
    for i := 0; i < length; i++ {
        n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(chars))))
        code = append(code, chars[n.Int64()])
    }
    return string(code)
}
  • crypto/rand.Reader 是操作系统提供的真随机源,比 math/rand 更适合安全场景
  • 显式剔除 IO01 等易读错字符,减少用户输入投诉
  • 长度建议固定为 4 或 6 位:太短易暴力,太长影响体验且不提升实质安全性

sync.Map 或 Redis 存储验证码并设过期时间

内存存储选 sync.Map 仅适用于单机调试;生产环境必须用 Redis,否则多实例下验证必然失败:

// 示例:Redis 存储(用 github.com/go-redis/redis/v9)
client.Set(ctx, "captcha:"+sessionID, code, 5*time.Minute)
  • 键名加前缀如 captcha:,避免和其他业务 key 冲突
  • 过期时间设为 5 分钟足够——再长增加暴力重试窗口,再短引发用户反复刷新
  • 务必在验证成功后立即 Del 对应 key,防止重复使用(replay attack)
  • 如果坚持用内存,sync.Map 无法自动过期,得自己起 goroutine 定时清理,不推荐

验证时严格区分大小写并校验时效性

前端传来的验证码常带空格或换行,后端不做清洗就直接比对会失败;同时 Redis 的 GET 返回空说明已过期或不存在:

立即学习“go语言免费学习笔记(深入)”;

func verifyCode(ctx context.Context, sessionID, input string) bool {
    val, err := client.Get(ctx, "captcha:"+sessionID).Result()
    if err == redis.Nil {
        return false // key 不存在(已过期或从未生成)
    }
    if err != nil {
        log.Printf("redis get error: %v", err)
        return false
    }
    return strings.TrimSpace(input) == val // 忽略首尾空白
}
  • strings.TrimSpace() 必须加,移动端软键盘常误触空格
  • 不要用 strings.EqualFold()——大小写不敏感会显著降低熵值,等同于少用一半字符集
  • Redis 返回 redis.Nil 表示 key 不存在,这是判断“过期”的唯一可靠方式,别查 TTL

真正难的不是生成那几行代码,而是存储生命周期管理:key 命名是否冲突、过期是否准时、验证后是否及时销毁、并发请求下是否出现竞态——这些细节没对齐,验证码就只是个摆设。

标签:# redis  # 前端  # git  # go  # github  # golang  # 操作系统  # go语言  # app  # session  # 后端  # win  # math  # 字符型  # 字符串  
在线客服
服务热线

服务热线

4008888355

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!