Golang图片验证码的使用

一、背景

最近在使用到Golang进行原生开发,注册和登录页面都涉及到图片验证码的功能。找了下第三方库的一些实现,发现了这个库用得还是蛮多的。并且支持很多类型的验证方式,例如支持数字类型、字母类型、音频验证码、中文验证码等等。

项目地址: https://github.com/mojocn/base64Captcha

官方文档地址: https://captcha.mojotv.cn/.netlify/functions/captcha

支持多种验证码类型(多种验证码驱动):

二、基本使用

1、生成验证码base64字符串

生成验证码的基本逻辑顺序如下:

0、需要准备存储验证码的一种驱动实现Store接口,库中有一个基于Store接口的内存存储方案的默认实现类: base64Captcha.DefaultMemStore

1、需要定义生成验证码类型的Driver驱动类实例, 配置验证码信息,例如图片大小、高度、模糊度等等

2、通过base64Captcha.NewCaptcha(&driver, store),生成验证码的base64字符串、验证码ID、验证码的答案、以及error信息, 最后重点拿到验证码ID、验证码base64字符串响应给前端进行展示

3、最后底层会将数据存储到store存储方式中,这个store类实现了Store接口,将验证码信息进行存储

Go 复制代码
// 这里我自己实现了一个基于Redis的Store存储驱动类
var store = captcha.NewRedisStore(db.GetRedisConn())

func GenCaptcha() (string, string) {
    // 设置验证码驱动类型,这里是数字运算类型的验证码 
    // 例如会生成几个数的基本运算, 最后求运算结果作为验证码结果
	driver := base64Captcha.DriverMath{          
		Height:     50,
		Width:      200,
		NoiseCount: 0,
	}
	captchaObj := base64Captcha.NewCaptcha(&driver, store)
	captchaId, b64s, _, err := captchaObj.Generate()
	if err != nil {
		panic(err.Error())
	}
	return captchaId, b64s // 拿到验证码ID、验证码的base64字符串
}

拿到验证码ID、验证码的base64字符串, 前端页面使用一个隐藏的input存储验证码ID、一个input作为表单提交验证码的值、一个img标签,将src设置为这个base64字符串,即可正常显示这个验证码.

前端局部代码如下:

显示效果如下:

后端查看Redis的存储信息: 可以看到验证码ID、验证码答案 8 x 5 = 40

2、后端校验验证码

后端校验的大致逻辑就是:

0、需要准备存储验证码的一种驱动实现store,库有有一个基于Store接口的内存存储方案的实现类base64Captcha.DefaultMemStore。 这个使用刚才和生成验证码的store变量一样即可

1、直接通过store对象,调用Verify方法,传递验证码ID、以及验证码答案即可, 验证结果返回true则代表通过, 返回false则表示不通过. 还有一个参数clear(bool), 代表执行验证后无论是否通过,都需要将这个验证码删除/作废

Go 复制代码
func VerifyCaptcha(captchaId string, answer string) bool {
	return store.Verify(captchaId, answer, true)
}

后端获取验证码,进行校验的代码截图:

3、Redis存储驱动代码: RedisStore

非生产环境代码,只是简单示例,请勿使用在生产环境。 因为有些逻辑没有做严格校验以及测试

Go 复制代码
package captcha

import (
	"context"
	"github.com/redis/go-redis/v9"
	"sync"
	"time"
)

const captchaKey = "string:captcha:"

var ctx = context.Background()

type RedisStore struct {
	redisClient *redis.Client
	mtx         sync.Mutex
}

func (r *RedisStore) Set(id string, value string) error {
	r.mtx.Lock()
	defer r.mtx.Unlock()
	key := captchaKey + id
	result := r.redisClient.SetNX(ctx, key, value, time.Second*60)
	if result.Err() != nil {
		return result.Err()
	}
	return nil
}

func (r *RedisStore) Get(id string, clear bool) string {
	r.mtx.Lock()
	defer r.mtx.Unlock()
	key := captchaKey + id
	result := r.redisClient.Get(ctx, key)
	if result.Err() != nil {
		return ""
	}
	if clear {
		go r.redisClient.Del(ctx, key)
	}
	return result.Val()
}

func (r *RedisStore) Verify(id, answer string, clear bool) bool {
	r.mtx.Lock()
	defer r.mtx.Unlock()
	key := captchaKey + id
	result := r.redisClient.Get(ctx, key)
	if result.Err() != nil {
		return false
	}
	storeAnswer := result.Val()
	if clear {
		go r.redisClient.Del(ctx, key)
	}
	return answer == storeAnswer
}

func NewRedisStore(redisClient *redis.Client) *RedisStore {
	return &RedisStore{
		redisClient: redisClient,
		mtx:         sync.Mutex{},
	}
}

三、总结

使用mojocn/base64Captcha库可以简单的生成验证码base64图片信息,方便了我们进行Web开发。 如果需要更高级或者详细的使用方式,请查看官方文档。

在实现Store存储驱动的时候,还要考虑我们的图片验证码例如访问频率限制、怎么针对有特征的客户端进行限流, 除了验证码有过期时间以外, 如是否有IP访问限流? 或者其他防御手段, 这样才能确保我们的后端Redis不会被恶意刷新,导致Redis内存撑爆了.

相关推荐
梵刹古音1 天前
【C语言】 字符数组相关库函数
c语言·开发语言·算法
微风中的麦穗1 天前
【MATLAB】MATLAB R2025a 详细下载安装图文指南:下一代科学计算与工程仿真平台
开发语言·matlab·开发工具·工程仿真·matlab r2025a·matlab r2025·科学计算与工程仿真
2601_949146531 天前
C语言语音通知API示例代码:基于标准C的语音接口开发与底层调用实践
c语言·开发语言
开源技术1 天前
Python Pillow 优化,打开和保存速度最快提高14倍
开发语言·python·pillow
学嵌入式的小杨同学1 天前
从零打造 Linux 终端 MP3 播放器!用 C 语言实现音乐自由
linux·c语言·开发语言·前端·vscode·ci/cd·vim
mftang1 天前
Python 字符串拼接成字节详解
开发语言·python
jasligea1 天前
构建个人智能助手
开发语言·python·自然语言处理
kokunka1 天前
【源码+注释】纯C++小游戏开发之射击小球游戏
开发语言·c++·游戏
云栖梦泽1 天前
易语言开发从入门到精通:补充篇·网络编程进阶+实用爬虫开发·API集成·代理IP配置·异步请求·防封禁优化
开发语言
java1234_小锋1 天前
Java高频面试题:SpringBoot为什么要禁止循环依赖?
java·开发语言·面试