package handlers import ( "net/http" "time" "goblog/database" "goblog/models" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" "golang.org/x/crypto/bcrypt" ) var jwtSecret = []byte("your-secret-key-change-in-production") func JWTSecret() []byte { return jwtSecret } // 登录请求 type LoginRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } // 注册请求 type RegisterRequest struct { Username string `json:"username" binding:"required,min=3,max=50"` Password string `json:"password" binding:"required,min=6"` Nickname string `json:"nickname"` Email string `json:"email" binding:"required,email"` } // JWT Claims type Claims struct { UserID uint `json:"user_id"` Username string `json:"username"` Role string `json:"role"` jwt.RegisteredClaims } // 登录 func Login(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } var user models.User if err := database.DB.Where("username = ?", req.Username).First(&user).Error; err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"}) return } if user.Status == 0 { c.JSON(http.StatusForbidden, gin.H{"error": "账号已被禁用"}) return } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"}) return } // 生成 JWT claims := Claims{ UserID: user.ID, Username: user.Username, Role: user.Role, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(jwtSecret) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "生成令牌失败"}) return } c.JSON(http.StatusOK, gin.H{ "token": tokenString, "user": gin.H{ "id": user.ID, "username": user.Username, "nickname": user.Nickname, "email": user.Email, "role": user.Role, "avatar": user.Avatar, }, }) } // 注册 func Register(c *gin.Context) { var req RegisterRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 检查用户名是否已存在 var count int64 database.DB.Model(&models.User{}).Where("username = ?", req.Username).Count(&count) if count > 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "用户名已存在"}) return } // 检查邮箱是否已存在 database.DB.Model(&models.User{}).Where("email = ?", req.Email).Count(&count) if count > 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "邮箱已被注册"}) return } // 加密密码 hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "密码加密失败"}) return } user := models.User{ Username: req.Username, Password: string(hashedPassword), Nickname: req.Nickname, Email: req.Email, Role: "user", Status: 1, } if err := database.DB.Create(&user).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "注册失败"}) return } c.JSON(http.StatusCreated, gin.H{ "message": "注册成功", "user": gin.H{ "id": user.ID, "username": user.Username, "nickname": user.Nickname, "email": user.Email, }, }) } // 获取当前用户信息 func GetCurrentUser(c *gin.Context) { userID, _ := c.Get("userID") var user models.User if err := database.DB.First(&user, userID).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"}) return } c.JSON(http.StatusOK, gin.H{"data": user}) } // 更新用户信息 func UpdateUser(c *gin.Context) { userID, _ := c.Get("userID") var user models.User if err := database.DB.First(&user, userID).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"}) return } var req struct { Nickname string `json:"nickname"` Email string `json:"email"` Avatar string `json:"avatar"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } updates := map[string]interface{}{} if req.Nickname != "" { updates["nickname"] = req.Nickname } if req.Email != "" { updates["email"] = req.Email } if req.Avatar != "" { updates["avatar"] = req.Avatar } if err := database.DB.Model(&user).Updates(updates).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "更新失败"}) return } c.JSON(http.StatusOK, gin.H{"data": user}) } // 修改密码 func ChangePassword(c *gin.Context) { userID, _ := c.Get("userID") var user models.User if err := database.DB.First(&user, userID).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"}) return } var req struct { OldPassword string `json:"old_password" binding:"required"` NewPassword string `json:"new_password" binding:"required,min=6"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.OldPassword)); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "原密码错误"}) return } hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "密码加密失败"}) return } user.Password = string(hashedPassword) if err := database.DB.Save(&user).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "修改密码失败"}) return } c.JSON(http.StatusOK, gin.H{"message": "密码修改成功"}) }