package captcha import ( "context" "git.noahlan.cn/noahlan/ntool-biz/core/config" "git.noahlan.cn/noahlan/ntool/nlog" "github.com/mojocn/base64Captcha" "github.com/redis/go-redis/v9" "image/color" "time" ) type RedisStore struct { Expiration time.Duration Prefix string Context context.Context Redis redis.Cmdable } // NewRedisStore returns a redis store for captcha. func NewRedisStore(conf config.RedisConf) *RedisStore { rdb := redis.NewClient(&redis.Options{ Network: conf.Network, Addr: conf.Addr, Username: conf.Username, Password: conf.Password, DB: conf.DB, }) return &RedisStore{ Expiration: time.Minute * 5, Prefix: "CAPTCHA_", Redis: rdb, Context: context.Background(), } } // UseWithCtx add context for captcha. func (r *RedisStore) UseWithCtx(ctx context.Context) base64Captcha.Store { r.Context = ctx return r } // Set sets the captcha KV to redis. func (r *RedisStore) Set(id string, value string) error { _, err := r.Redis.SetEx(r.Context, r.Prefix+id, value, r.Expiration).Result() if err != nil { nlog.Errorw("error occurs when captcha key sets to redis", nlog.Field("detail", err)) return err } return nil } // Get gets the captcha KV from redis. func (r *RedisStore) Get(key string, clear bool) string { val, err := r.Redis.Get(r.Context, key).Result() if err != nil { nlog.Errorw("error occurs when captcha key gets from redis", nlog.Field("detail", err)) return "" } if clear { _, err := r.Redis.Del(r.Context, key).Result() if err != nil { nlog.Errorw("error occurs when captcha key deletes from redis", nlog.Field("detail", err)) return "" } } return val } // Verify verifies the captcha whether it is correct. func (r *RedisStore) Verify(id, answer string, clear bool) bool { key := r.Prefix + id v := r.Get(key, clear) return v == answer } // MustNewRedisCaptcha returns the captcha using redis, it will panic when error occur func MustNewRedisCaptcha(c Config, redisConf config.RedisConf) *base64Captcha.Captcha { driver := NewDriver(c) store := NewRedisStore(redisConf) return base64Captcha.NewCaptcha(driver, store) } func NewDriver(c Config) base64Captcha.Driver { var driver base64Captcha.Driver bgColor := &color.RGBA{ R: 254, G: 254, B: 254, A: 254, } fonts := []string{ "3Dumb.ttf", "ApothecaryFont.ttf", "Comismsh.ttf", "DENNEthree-dee.ttf", "DeborahFancyDress.ttf", "Flim-Flam.ttf", "RitaSmith.ttf", "actionj.ttf", "chromohv.ttf", } switch c.Driver { case "digit": driver = base64Captcha.NewDriverDigit(c.ImgHeight, c.ImgWidth, c.KeyLen, 0.7, 80) case "string": driver = base64Captcha.NewDriverString(c.ImgHeight, c.ImgWidth, 0, 0, c.KeyLen, "qwertyupasdfghjkzxcvbnm23456789", bgColor, nil, fonts) case "math": driver = base64Captcha.NewDriverMath(c.ImgHeight, c.ImgWidth, 0, 0, bgColor, nil, fonts) case "chinese": // TODO 读取中文列表 driver = base64Captcha.NewDriverChinese(c.ImgHeight, c.ImgWidth, 0, 0, c.KeyLen, "埃里克森等级分类三级独立开发叫我阿胶发凯撒就看来附件为投靠子女的咖啡", bgColor, nil, fonts) default: driver = base64Captcha.NewDriverDigit(c.ImgHeight, c.ImgWidth, c.KeyLen, 0.7, 80) } return driver }