LicenseManger/internal/service/captcha.go

101 lines
2.4 KiB
Go
Raw Permalink Normal View History

2024-11-14 14:55:43 +00:00
package service
import (
"errors"
"licserver/internal/model"
"licserver/internal/utils"
"strings"
"time"
"github.com/mojocn/base64Captcha"
"gorm.io/gorm"
)
type CaptchaService struct {
db *gorm.DB
emailConfig *utils.EmailConfig
store base64Captcha.Store
}
func NewCaptchaService(db *gorm.DB, emailConfig *utils.EmailConfig) *CaptchaService {
return &CaptchaService{
db: db,
emailConfig: emailConfig,
store: base64Captcha.DefaultMemStore,
}
}
func (s *CaptchaService) SendEmailCaptcha(email, captchaType string) error {
// 检查是否存在未过期的验证码
var count int64
s.db.Model(&model.Captcha{}).
Where("target = ? AND type = ? AND expires_at > ? AND used = ?",
email, captchaType, time.Now(), false).
Count(&count)
if count > 0 {
return errors.New("请勿频繁发送验证码")
}
// 生成验证码
code, err := utils.GenerateCaptcha()
if err != nil {
return err
}
// 保存验证码
captcha := model.Captcha{
Code: code,
Type: captchaType,
Target: email,
ExpiresAt: time.Now().Add(5 * time.Minute),
Used: false,
}
if err := s.db.Create(&captcha).Error; err != nil {
return err
}
// 发送验证码邮件
emailService := utils.NewEmailService(s.emailConfig)
content := utils.GenerateEmailCaptchaContent(code, email, captchaType)
return emailService.SendEmail(email, "验证码", content)
}
func (s *CaptchaService) VerifyCaptcha(target, captchaType, code string) error {
var captcha model.Captcha
err := s.db.Where("target = ? AND type = ? AND code = ? AND used = ? AND expires_at > ?",
target, captchaType, code, false, time.Now()).
First(&captcha).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return errors.New("验证码无效或已过期")
}
return err
}
// 标记验证码为已使用
return s.db.Model(&captcha).Update("used", true).Error
}
// 生成图片验证码
func (s *CaptchaService) GenerateImageCaptcha() (string, string, error) {
driver := base64Captcha.NewDriverDigit(80, 240, 6, 0.7, 80)
c := base64Captcha.NewCaptcha(driver, s.store)
id, b64s, err := c.Generate()
if err != nil {
return "", "", err
}
// 确保返回的base64字符串不包含前缀
b64s = strings.TrimPrefix(b64s, "data:image/png;base64,")
return id, b64s, nil
}
// 验证图片验证码
func (s *CaptchaService) VerifyImageCaptcha(id, code string) bool {
return s.store.Verify(id, code, true)
}