package auth import ( "cls-server/internal/application/auth" "cls-server/internal/interfaces" "cls-server/pkg/logger" jwt "github.com/appleboy/gin-jwt/v2" "github.com/gin-gonic/gin" "net/http" auth_middleware "cls-server/internal/infrastructure/middleware/auth" ) type AuthHandler struct { captchaService *auth.CaptchaService service *auth.AuthService log logger.Logger } var _ interfaces.Handler = (*AuthHandler)(nil) func NewAuthHandler(captcha *auth.CaptchaService, service *auth.AuthService, log logger.New) *AuthHandler { return &AuthHandler{captcha, service, log("cls:interfaces:auth")} } func (h *AuthHandler) RegisterRouters(app gin.IRouter) { auth := app.Group("/auth") { auth.POST("/login", h.Login) auth.GET("/image-captcha", h.GetImageCaptcha) auth.GET("/captcha", h.GetSmsCaptcha) auth.POST("/verify-sms", h.VerifySmsCaptcha) } } // getUserIdentifier 从 JWT token 中获取用户标识 func (h *AuthHandler) getUserIdentifier(c *gin.Context) string { claims := jwt.ExtractClaims(c) if claims["phone"] != nil { return claims["phone"].(string) } if claims["guest_id"] != nil { return claims["guest_id"].(string) } return "" } // isGuest 判断当前用户是否为游客 func (h *AuthHandler) isGuest(c *gin.Context) bool { claims := jwt.ExtractClaims(c) return claims["guest_id"] != nil } // GetSmsCaptcha 获取短信验证码 func (h *AuthHandler) GetSmsCaptcha(c *gin.Context) { // 生成短信验证码 captcha, err := h.captchaService.GenerateSmsCaptcha(c.Query("username")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{ "message": "验证码已发送", "resetAfter": captcha.ResetAfter, }) } // GetImageCaptcha 获取图片验证码 func (h *AuthHandler) GetImageCaptcha(c *gin.Context) { // 生成验证码 captcha, err := h.captchaService.GenerateImageCaptcha(c.Query("u")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.String(http.StatusOK, captcha) } // VerifySmsCaptcha 验证短信验证码 func (h *AuthHandler) VerifySmsCaptcha(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"message": "验证成功"}) } func (h *AuthHandler) Login(c *gin.Context) { var req struct { Username string `json:"username" binding:"required"` CaptchaCode string `json:"smsCode" binding:"required"` Password string `json:"password" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "参数不完整"}) return } err := h.captchaService.VerifySmsCaptcha(req.Username, req.CaptchaCode) if err != nil { c.AbortWithStatus(http.StatusInternalServerError) return } token, err := h.service.LoginByPassword(req.Username, req.Password) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } else { c.JSON(http.StatusOK, token) } } // DecodeToken 解析 token 并返回原始的加密手机号 func (h *AuthHandler) DecodeToken(c *gin.Context) { var req struct { Token string `json:"token" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "参数不完整"}) return } // 通过 auth 模块获取密钥 secretKey := h.service.GetJWTSecretKey() // 调用 DecodeTokenStatic 方法解析 token encryptedPhone, err := auth_middleware.DecodeTokenStatic(req.Token, []byte(secretKey)) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{ "encryptedPhone": encryptedPhone, }) }