贝利信息

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

日期:2026-01-04 00:00 / 作者:P粉602998670
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)
}

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

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

// 示例:Redis 存储(用 github.com/go-redis/redis/v9)
client.Set(ctx, "captcha:"+sessionID, code, 5*time.Minute)

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

前端传来的验证码常带空格或换行,后端不做清洗就直接比对会失败;同时 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 // 忽略首尾空白
}

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