Golang圖片驗(yàn)證碼的使用方法
一、背景
最近在使用到Golang進(jìn)行原生開發(fā),注冊(cè)和登錄頁面都涉及到圖片驗(yàn)證碼的功能。找了下第三方庫的一些實(shí)現(xiàn),發(fā)現(xiàn)了這個(gè)庫用得還是蠻多的。并且支持很多類型的驗(yàn)證方式,例如支持?jǐn)?shù)字類型、字母類型、音頻驗(yàn)證碼、中文驗(yàn)證碼等等。
項(xiàng)目地址: https://github.com/mojocn/base64Captcha
官方文檔地址: https://captcha.mojotv.cn/.netlify/functions/captcha
支持多種驗(yàn)證碼類型(多種驗(yàn)證碼驅(qū)動(dòng)):
二、基本使用
1、生成驗(yàn)證碼base64字符串
生成驗(yàn)證碼的基本邏輯順序如下:
0、需要準(zhǔn)備存儲(chǔ)驗(yàn)證碼的一種驅(qū)動(dòng)實(shí)現(xiàn)Store接口,庫中有一個(gè)基于Store接口的內(nèi)存存儲(chǔ)方案的默認(rèn)實(shí)現(xiàn)類: base64Captcha.DefaultMemStore
1、需要定義生成驗(yàn)證碼類型的Driver驅(qū)動(dòng)類實(shí)例, 配置驗(yàn)證碼信息,例如圖片大小、高度、模糊度等等
2、通過base64Captcha.NewCaptcha(&driver, store),生成驗(yàn)證碼的base64字符串、驗(yàn)證碼ID、驗(yàn)證碼的答案、以及error信息, 最后重點(diǎn)拿到驗(yàn)證碼ID、驗(yàn)證碼base64字符串響應(yīng)給前端進(jìn)行展示
3、最后底層會(huì)將數(shù)據(jù)存儲(chǔ)到store存儲(chǔ)方式中,這個(gè)store類實(shí)現(xiàn)了Store接口,將驗(yàn)證碼信息進(jìn)行存儲(chǔ)
// 這里我自己實(shí)現(xiàn)了一個(gè)基于Redis的Store存儲(chǔ)驅(qū)動(dòng)類 var store = captcha.NewRedisStore(db.GetRedisConn()) func GenCaptcha() (string, string) { // 設(shè)置驗(yàn)證碼驅(qū)動(dòng)類型,這里是數(shù)字運(yùn)算類型的驗(yàn)證碼 // 例如會(huì)生成幾個(gè)數(shù)的基本運(yùn)算, 最后求運(yùn)算結(jié)果作為驗(yàn)證碼結(jié)果 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 // 拿到驗(yàn)證碼ID、驗(yàn)證碼的base64字符串 }
拿到驗(yàn)證碼ID、驗(yàn)證碼的base64字符串, 前端頁面使用一個(gè)隱藏的input存儲(chǔ)驗(yàn)證碼ID、一個(gè)input作為表單提交驗(yàn)證碼的值、一個(gè)img標(biāo)簽,將src設(shè)置為這個(gè)base64字符串,即可正常顯示這個(gè)驗(yàn)證碼.
前端局部代碼如下:
顯示效果如下:
后端查看Redis的存儲(chǔ)信息: 可以看到驗(yàn)證碼ID、驗(yàn)證碼答案 8 x 5 = 40
2、后端校驗(yàn)驗(yàn)證碼
后端校驗(yàn)的大致邏輯就是:
0、需要準(zhǔn)備存儲(chǔ)驗(yàn)證碼的一種驅(qū)動(dòng)實(shí)現(xiàn)store,庫有有一個(gè)基于Store接口的內(nèi)存存儲(chǔ)方案的實(shí)現(xiàn)類base64Captcha.DefaultMemStore。 這個(gè)使用剛才和生成驗(yàn)證碼的store變量一樣即可
1、直接通過store對(duì)象,調(diào)用Verify方法,傳遞驗(yàn)證碼ID、以及驗(yàn)證碼答案即可, 驗(yàn)證結(jié)果返回true則代表通過, 返回false則表示不通過. 還有一個(gè)參數(shù)clear(bool), 代表執(zhí)行驗(yàn)證后無論是否通過,都需要將這個(gè)驗(yàn)證碼刪除/作廢
func VerifyCaptcha(captchaId string, answer string) bool { return store.Verify(captchaId, answer, true) }
后端獲取驗(yàn)證碼,進(jìn)行校驗(yàn)的代碼截圖:
3、Redis存儲(chǔ)驅(qū)動(dòng)代碼: RedisStore
非生產(chǎn)環(huán)境代碼,只是簡單示例,請(qǐng)勿使用在生產(chǎn)環(huán)境。 因?yàn)橛行┻壿嫑]有做嚴(yán)格校驗(yàn)以及測試
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{}, } }
三、總結(jié)
使用mojocn/base64Captcha庫可以簡單的生成驗(yàn)證碼base64圖片信息,方便了我們進(jìn)行Web開發(fā)。 如果需要更高級(jí)或者詳細(xì)的使用方式,請(qǐng)查看官方文檔。
在實(shí)現(xiàn)Store存儲(chǔ)驅(qū)動(dòng)的時(shí)候,還要考慮我們的圖片驗(yàn)證碼例如訪問頻率限制、怎么針對(duì)有特征的客戶端進(jìn)行限流, 除了驗(yàn)證碼有過期時(shí)間以外, 如是否有IP訪問限流? 或者其他防御手段, 這樣才能確保我們的后端Redis不會(huì)被惡意刷新,導(dǎo)致Redis內(nèi)存撐爆了.
到此這篇關(guān)于Golang圖片驗(yàn)證碼的使用的文章就介紹到這了,更多相關(guān)Golang圖片驗(yàn)證碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go-Web框架中AOP方案的實(shí)現(xiàn)方式
本文主要介紹了Go-Web框架中AOP方案的實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06golang復(fù)用http.request.body的方法示例
這篇文章主要給大家介紹了關(guān)于golang復(fù)用http.request.body的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10Golang使用channel實(shí)現(xiàn)數(shù)據(jù)匯總的方法詳解
這篇文章主要為大家詳細(xì)介紹了在并發(fā)編程中數(shù)據(jù)匯總的問題,并探討了在并發(fā)環(huán)境下使用互斥鎖和通道兩種方式來保證數(shù)據(jù)安全性的方法,需要的可以參考一下2023-05-05深入解析Go語言中HTTP請(qǐng)求處理的底層實(shí)現(xiàn)
本文將詳細(xì)介紹?Go?語言中?HTTP?請(qǐng)求處理的底層機(jī)制,包括工作流程、創(chuàng)建?Listen?Socket?監(jiān)聽端口、接收客戶端請(qǐng)求并建立連接以及處理客戶端請(qǐng)求并返回響應(yīng)等,需要的朋友可以參考下2023-05-05