captcha.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // Package captcha 处理图片验证码逻辑,支持: 1. 生成图片验证码 2. 校验图片验证码
  2. // 支持的存储:redis, memory
  3. package captcha
  4. import (
  5. "sync"
  6. "github.com/mojocn/base64Captcha"
  7. "github.com/runningwater/gohub/pkg/app"
  8. "github.com/runningwater/gohub/pkg/config"
  9. "github.com/runningwater/gohub/pkg/redis"
  10. )
  11. type Captcha struct {
  12. base64Captcha *base64Captcha.Captcha
  13. }
  14. // 确保 internalCaptcha 只初始化一次
  15. // 通过 sync.Once 确保线程安全
  16. var one sync.Once
  17. var internalCaptcha *Captcha
  18. // NewCaptcha 创建一个新的验证码实例
  19. func NewCaptcha() *Captcha {
  20. one.Do(func() {
  21. // 初始化 Captcha 实例
  22. internalCaptcha = &Captcha{}
  23. // 使用 redis 作为存储引擎,并设置 key 的前缀
  24. store := RedisStore{
  25. RedisClient: redis.Redis,
  26. KeyPrefix: config.GetString("app.name") + ":captcha:",
  27. }
  28. // 配置 base64Captcha 驱动信息
  29. driver := base64Captcha.NewDriverDigit(
  30. config.GetInt("captcha.height"), // 高度
  31. config.GetInt("captcha.width"), // 宽度
  32. config.GetInt("captcha.length"), // 长度
  33. config.GetFloat64("captcha.maxskew"), // 最大倾斜角度
  34. config.GetInt("captcha.dotcount"), // 图片背景里的混淆点数量
  35. )
  36. // 创建 base64Captcha 实例
  37. internalCaptcha.base64Captcha = base64Captcha.NewCaptcha(driver, &store)
  38. })
  39. return internalCaptcha
  40. }
  41. // GenerateCaptcha 生成验证码
  42. func (c *Captcha) GenerateCaptcha() (id, b64s, answer string, err error) {
  43. return c.base64Captcha.Generate()
  44. }
  45. // VerifyCaptcha 校验验证码
  46. func (c *Captcha) VerifyCaptcha(id, answer string) (match bool) {
  47. // 方便本地开发调试
  48. if !app.IsProduction() && id == config.GetString("captcha.testing_key") {
  49. return true
  50. }
  51. // 第三个参数是验证后是否删除,我们选择 false
  52. // 这样方便用户多次提交,防止表单提交错误需要多次输入图片验证码
  53. return c.base64Captcha.Verify(id, answer, false)
  54. }