feat: Enhance dependency injection and service integration
- Updated main.go to initialize email service and include it in the dependency injection container. - Refactored handlers to utilize context in service method calls, improving consistency and error handling. - Introduced new service options for upload, security, and captcha services, enhancing modularity and testability. - Removed unused repository implementations to streamline the codebase. This commit continues the effort to improve the architecture by ensuring all services are properly injected and utilized across the application.
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/wenlng/go-captcha-assets/resources/imagesv2"
|
||||
"github.com/wenlng/go-captcha-assets/resources/tiles"
|
||||
"github.com/wenlng/go-captcha/v2/slide"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -72,48 +73,71 @@ type RedisData struct {
|
||||
Ty int `json:"ty"` // 滑块目标Y坐标
|
||||
}
|
||||
|
||||
// GenerateCaptchaData 提取生成验证码的相关信息
|
||||
func GenerateCaptchaData(ctx context.Context, redisClient *redis.Client) (string, string, string, int, error) {
|
||||
// captchaService CaptchaService的实现
|
||||
type captchaService struct {
|
||||
redis *redis.Client
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewCaptchaService 创建CaptchaService实例
|
||||
func NewCaptchaService(redisClient *redis.Client, logger *zap.Logger) CaptchaService {
|
||||
return &captchaService{
|
||||
redis: redisClient,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// Generate 生成验证码
|
||||
func (s *captchaService) Generate(ctx context.Context) (masterImg, tileImg, captchaID string, y int, err error) {
|
||||
// 生成uuid作为验证码进程唯一标识
|
||||
captchaID := uuid.NewString()
|
||||
captchaID = uuid.NewString()
|
||||
if captchaID == "" {
|
||||
return "", "", "", 0, errors.New("生成验证码唯一标识失败")
|
||||
err = errors.New("生成验证码唯一标识失败")
|
||||
return
|
||||
}
|
||||
|
||||
captData, err := slideTileCapt.Generate()
|
||||
if err != nil {
|
||||
return "", "", "", 0, fmt.Errorf("生成验证码失败: %w", err)
|
||||
err = fmt.Errorf("生成验证码失败: %w", err)
|
||||
return
|
||||
}
|
||||
blockData := captData.GetData()
|
||||
if blockData == nil {
|
||||
return "", "", "", 0, errors.New("获取验证码数据失败")
|
||||
err = errors.New("获取验证码数据失败")
|
||||
return
|
||||
}
|
||||
block, _ := json.Marshal(blockData)
|
||||
var blockMap map[string]interface{}
|
||||
|
||||
if err := json.Unmarshal(block, &blockMap); err != nil {
|
||||
return "", "", "", 0, fmt.Errorf("反序列化为map失败: %w", err)
|
||||
if err = json.Unmarshal(block, &blockMap); err != nil {
|
||||
err = fmt.Errorf("反序列化为map失败: %w", err)
|
||||
return
|
||||
}
|
||||
// 提取x和y并转换为int类型
|
||||
tx, ok := blockMap["x"].(float64)
|
||||
if !ok {
|
||||
return "", "", "", 0, errors.New("无法将x转换为float64")
|
||||
err = errors.New("无法将x转换为float64")
|
||||
return
|
||||
}
|
||||
var x = int(tx)
|
||||
ty, ok := blockMap["y"].(float64)
|
||||
if !ok {
|
||||
return "", "", "", 0, errors.New("无法将y转换为float64")
|
||||
err = errors.New("无法将y转换为float64")
|
||||
return
|
||||
}
|
||||
var y = int(ty)
|
||||
var mBase64, tBase64 string
|
||||
mBase64, err = captData.GetMasterImage().ToBase64()
|
||||
y = int(ty)
|
||||
|
||||
masterImg, err = captData.GetMasterImage().ToBase64()
|
||||
if err != nil {
|
||||
return "", "", "", 0, fmt.Errorf("主图转换为base64失败: %w", err)
|
||||
err = fmt.Errorf("主图转换为base64失败: %w", err)
|
||||
return
|
||||
}
|
||||
tBase64, err = captData.GetTileImage().ToBase64()
|
||||
tileImg, err = captData.GetTileImage().ToBase64()
|
||||
if err != nil {
|
||||
return "", "", "", 0, fmt.Errorf("滑块图转换为base64失败: %w", err)
|
||||
err = fmt.Errorf("滑块图转换为base64失败: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
redisData := RedisData{
|
||||
Tx: x,
|
||||
Ty: y,
|
||||
@@ -123,31 +147,30 @@ func GenerateCaptchaData(ctx context.Context, redisClient *redis.Client) (string
|
||||
expireTime := 300 * time.Second
|
||||
|
||||
// 使用注入的Redis客户端
|
||||
if err := redisClient.Set(
|
||||
ctx,
|
||||
redisKey,
|
||||
redisDataJSON,
|
||||
expireTime,
|
||||
); err != nil {
|
||||
return "", "", "", 0, fmt.Errorf("存储验证码到redis失败: %w", err)
|
||||
if err = s.redis.Set(ctx, redisKey, redisDataJSON, expireTime); err != nil {
|
||||
err = fmt.Errorf("存储验证码到redis失败: %w", err)
|
||||
return
|
||||
}
|
||||
return mBase64, tBase64, captchaID, y - 10, nil
|
||||
|
||||
// 返回时 y 需要减10
|
||||
y = y - 10
|
||||
return
|
||||
}
|
||||
|
||||
// VerifyCaptchaData 验证用户验证码
|
||||
func VerifyCaptchaData(ctx context.Context, redisClient *redis.Client, dx int, id string) (bool, error) {
|
||||
// Verify 验证验证码
|
||||
func (s *captchaService) Verify(ctx context.Context, dx int, captchaID string) (bool, error) {
|
||||
// 测试环境下直接通过验证
|
||||
cfg, err := config.GetConfig()
|
||||
if err == nil && cfg.IsTestEnvironment() {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
redisKey := redisKeyPrefix + id
|
||||
redisKey := redisKeyPrefix + captchaID
|
||||
|
||||
// 从Redis获取验证信息,使用注入的客户端
|
||||
dataJSON, err := redisClient.Get(ctx, redisKey)
|
||||
dataJSON, err := s.redis.Get(ctx, redisKey)
|
||||
if err != nil {
|
||||
if redisClient.Nil(err) { // 使用封装客户端的Nil错误
|
||||
if s.redis.Nil(err) { // 使用封装客户端的Nil错误
|
||||
return false, errors.New("验证码已过期或无效")
|
||||
}
|
||||
return false, fmt.Errorf("redis查询失败: %w", err)
|
||||
@@ -162,9 +185,9 @@ func VerifyCaptchaData(ctx context.Context, redisClient *redis.Client, dx int, i
|
||||
|
||||
// 验证后立即删除Redis记录(防止重复使用)
|
||||
if ok {
|
||||
if err := redisClient.Del(ctx, redisKey); err != nil {
|
||||
if err := s.redis.Del(ctx, redisKey); err != nil {
|
||||
// 记录警告但不影响验证结果
|
||||
log.Printf("删除验证码Redis记录失败: %v", err)
|
||||
s.logger.Warn("删除验证码Redis记录失败", zap.Error(err))
|
||||
}
|
||||
}
|
||||
return ok, nil
|
||||
|
||||
Reference in New Issue
Block a user