在gin框架中实现图片验证
这里使用的库是"github.com/mojocn/base64Captcha",可以在CaptMake()中去修改来达到自己想要的验证码的样式
package main
import (
"demo/models"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
type test struct {
id string `json:"id"`
b64s string `json:"b64s"`
}
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
id,b64s,err := models.CaptMake()
if err != nil {
fmt.Println(err)
}
r.GET("/test", func(c *gin.Context) {
c.JSON(http.StatusOK,gin.H{
"id" : id,
"testId" : b64s,
})
})
r.POST("/testPost", func(c *gin.Context) {
var t = new(test)
c.ShouldBindJSON(t)
if flag := models.CaptVerify(t.id,t.b64s); flag == true {
fmt.Println("验证验证码成功")
} else {
fmt.Println("验证验证码失败") }
})
r.Run()
}
package models
import (
"github.com/mojocn/base64Captcha"
"image/color"
)
var store = base64Captcha.DefaultMemStore
//生成验证码
func CaptMake() (id, b64s string, err error) {
var driver base64Captcha.Driver
// 配置验证码信息
driverString := base64Captcha.DriverString{
Height: 40,
Width: 100,
NoiseCount: 0,
ShowLineOptions: 2 | 4,
Length: 4,
Source: "1234567890qwertyuioplkjhgfdsazxcvbnm", BgColor: &color.RGBA{
R: 3, G: 102, B: 214, A: 125,
},
Fonts: []string{"wqy-microhei.ttc"}, }
//ConvertFonts 按名称加载字体
driver = driverString.ConvertFonts()
//创建 Captcha
captcha := base64Captcha.NewCaptcha(driver, store) //Generate 生成随机 id、base64 图像字符串
lid, lb64s, lerr := captcha.Generate()
return lid, lb64s, lerr
}
//验证 captcha 是否正确
func CaptVerify(id string, capt string) bool {
if store.Verify(id, capt, false) {
return true
} else {
return false
}
}
解决分布式的验证问题
在分布式的场景中,可能我们在生成图形验证码和最终验证验证码的机器不是同一个,这个时候就会产生错误。
为了解决这个问题,我们可以使用redis,将每一次从服务端得到的数据存放到redis中,然后每一次验证的时候直接到redis中去验证。
为了减少内存的压力,我们可以在每一次验证完数据的时候将redis存放的数据删除。 这几个seet之类的方法是为了实现store接口,set是自动调用的。
package models
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"github.com/mojocn/base64Captcha"
"image/color"
"time"
)
var store base64Captcha.Store = RedisStore{}
//生成验证码
func CaptMake() (id, b64s string, err error) {
var driver base64Captcha.Driver
// 配置验证码信息
driverString := base64Captcha.DriverString{
Height: 40,
Width: 100,
NoiseCount: 0,
ShowLineOptions: 2 | 4,
Length: 4,
Source: "1234567890qwertyuioplkjhgfdsazxcvbnm", BgColor: &color.RGBA{
R: 3, G: 102, B: 214, A: 125,
},
Fonts: []string{"wqy-microhei.ttc"}, }
//ConvertFonts 按名称加载字体
driver = driverString.ConvertFonts()
//创建 Captcha
captcha := base64Captcha.NewCaptcha(driver, store) //Generate 生成随机 id、base64 图像字符串
lid, lb64s, lerr := captcha.Generate()
return lid, lb64s, lerr
}
//验证 captcha 是否正确
func CaptVerify(id string, capt string) bool {
if store.Verify(id, capt, false) {
return true
} else {
return false
}
}
var RedisDb *redis.Client
func init() {
var ctx = context.Background()
RedisDb = redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379", Password: "", // no password set DB: 0, // use default DB
})
_, err := RedisDb.Ping(ctx).Result()
if err != nil {
println(err)
}
}
var ctx = context.Background()
const CAPTCHA = "captcha:"
type RedisStore struct {
}
//实现设置 captcha 的方法
func (r RedisStore) Set(id string, value string) error {
key := CAPTCHA + id
err := RedisDb.Set(ctx, key, value, time.Minute*2).Err()
return err
}
//实现获取 captcha 的方法
func (r RedisStore) Get(id string, clear bool) string {
key := CAPTCHA + id
val, err := RedisDb.Get(ctx, key).Result() ;if err != nil {
fmt.Println(err)
return "" }
if clear {
err := RedisDb.Del(ctx, key).Err(); if err != nil {
fmt.Println(err)
return "" }
}
return val }
//实现验证 captcha 的方法
func (r RedisStore) Verify(id, answer string, clear bool) bool {
v := RedisStore{}.Get(id, clear)
fmt.Println("key:"+id+";value:"+v+";answer:"+answer)
return v == answer
}