一、背景
最近在使用到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接口,将验证码信息进行存储
// 这里我自己实现了一个基于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), 代表执行验证后无论是否通过,都需要将这个验证码删除/作废
func verifycaptcha(captchaid string, answer string) bool { return store.verify(captchaid, answer, true) }
后端获取验证码,进行校验的代码截图:
3、redis存储驱动代码: redisstore
非生产环境代码,只是简单示例,请勿使用在生产环境。 因为有些逻辑没有做严格校验以及测试
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内存撑爆了.
到此这篇关于golang图片验证码的使用的文章就介绍到这了,更多相关golang图片验证码内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论