| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- package core
- import (
- "bytes"
- "context"
- "embed"
- "encoding/base64"
- "fmt"
- "github.com/afocus/captcha"
- "github.com/emirpasic/gods/maps/hashmap"
- "github.com/redis/go-redis/v9"
- "go_server/base/config"
- "go_server/utils"
- "image/color"
- "image/png"
- "io/fs"
- "strings"
- "time"
- )
- type CaptchaEngine struct {
- }
- //go:embed *.ttf
- var fontFs embed.FS
- var cap *captcha.Captcha
- var capStore *hashmap.Map
- const (
- CaptchaImgWidth = 200
- CaptchaImgHeight = 60
- CaptchaDisturbance = captcha.NORMAL // 干扰度
- CaptchaKeyLong = 4
- CaptchaStrType = captcha.NUM // 字符类型
- CaptchaOpenTimes = 3 // 触发验证码次数
- CaptchaTimeOut = 30 // 过期时间 S
- )
- func CapEngine() *CaptchaEngine {
- if cap == nil {
- cap = captcha.New()
- // 设置字体
- //_ = capCore.SetFont("./comic.ttf") // 这里改为绝对路径
- buf, err := fs.ReadFile(fontFs, "comic.ttf")
- if err != nil {
- panic(err)
- }
- err = cap.AddFontFromBytes(buf)
- if err != nil {
- panic(err)
- }
- // 设置验证码大小 128 64
- cap.SetSize(CaptchaImgWidth, CaptchaImgHeight)
- // 设置干扰强度
- cap.SetDisturbance(CaptchaDisturbance)
- // 设置前景色 可以多个 随机替换文字颜色 默认黑色
- // 第一位:4690D8
- // 第二位:F19A80
- // 第三位:9CD881
- // 第四位:CB7590
- cap.SetFrontColor(color.RGBA{70, 144, 216, 255},
- color.RGBA{156, 216, 129, 255},
- color.RGBA{203, 117, 144, 255},
- color.RGBA{241, 154, 128, 255},
- )
- // 设置背景色 可以多个 随机替换背景色 默认白色
- //capCore.SetBkgColor(color.RGBA{255, 0, 0, 255}, color.RGBA{0, 0, 255, 255}, color.RGBA{0, 153, 0, 255})
- //cap.SetBkgColor(color.RGBA{33, 33, 33, 255})
- cap.SetBkgColor(color.RGBA{255, 0, 0, 100}, color.RGBA{0, 0, 255, 100}, color.RGBA{0, 153, 0, 100})
- }
- if capStore == nil {
- capStore = hashmap.New()
- }
- return &CaptchaEngine{}
- }
- func (c *CaptchaEngine) Generate() (bs64 string, cid string) {
- img, code := c.getImg()
- cid = base64.StdEncoding.EncodeToString([]byte(utils.GenStrUuid()))
- // todo: set cid to store
- capStore.Put(cid, fmt.Sprintf("%s", code))
- w := bytes.NewBuffer(nil)
- _ = png.Encode(w, img)
- return fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(w.Bytes())), cid
- }
- func (c *CaptchaEngine) Verify(cid, answer string) (match bool) {
- if answer == config.VerifyCode {
- return true
- }
- vv, ok := capStore.Get(cid)
- if !ok {
- return ok
- }
- v, _ := vv.(string)
- vvLower := strings.ToLower(strings.TrimSpace(v))
- capStore.Remove(cid)
- return vvLower == strings.ToLower(strings.TrimSpace(answer))
- }
- func (c *CaptchaEngine) VerifyAndSendTick(cid, answer string) (string, bool) {
- if c.Verify(cid, answer) {
- ticket := base64.StdEncoding.EncodeToString([]byte(utils.GenStrUuid()))
- capStore.Put(ticket, true)
- return ticket, true
- }
- return "", false
- }
- func (c *CaptchaEngine) VerifyTick(ticket string) bool {
- _, ok := capStore.Get(ticket)
- return ok
- }
- func (c *CaptchaEngine) RemoveTick(ticket string) {
- capStore.Remove(ticket)
- }
- func (*CaptchaEngine) getImg() (*captcha.Image, string) {
- return cap.Create(CaptchaKeyLong, CaptchaStrType)
- }
- func (c *CaptchaEngine) capIpKey(ip string) string {
- return fmt.Sprintf("Cap:%s", ip)
- }
- func (c *CaptchaEngine) CapCheck(redisDb redis.UniversalClient, ip string) (int, bool) {
- vCmd := redisDb.Get(context.Background(), c.capIpKey(ip))
- t, err := vCmd.Int()
- if err != nil {
- return t, false
- }
- return t, t > CaptchaOpenTimes
- }
- func (c *CaptchaEngine) CapAdd(redisDb redis.UniversalClient, ip string) string {
- vCmd := redisDb.Get(context.Background(), c.capIpKey(ip))
- t, _ := vCmd.Int()
- sCmd := redisDb.Set(context.Background(), c.capIpKey(ip), t+1, time.Minute*time.Duration(CaptchaTimeOut))
- return sCmd.Val()
- }
- func (c *CaptchaEngine) CapClear(redisDb redis.UniversalClient, ip string) int64 {
- iCmd := redisDb.Del(context.Background(), c.capIpKey(ip))
- return iCmd.Val()
- }
|