diff --git a/.history/README_20240925151839.md b/.history/README_20240925151839.md new file mode 100644 index 0000000..190a180 --- /dev/null +++ b/.history/README_20240925151839.md @@ -0,0 +1 @@ +123 diff --git a/.history/README_20240925162207.md b/.history/README_20240925162207.md new file mode 100644 index 0000000..735a3bc --- /dev/null +++ b/.history/README_20240925162207.md @@ -0,0 +1,31 @@ +# TestFB +> 使用Go语言,实现用户登录、获取用户信息、修改用户信息。 + +## 工程要求:结构化工程,更加规范的代码编写。 +## 工程使用的模块或技术: +1. Go语言 +2. fiber框架 +3. Gorm ORM框架 +4. fiber下的storage/redis v3模块 +5. JWT身份验证,存储在redis中 +6. mysql,使用fiber下的storage/mysql v2模块 +7. 日志,使用fiber自带的日志模块 + +## mysql模块 +1. 数据库地址:localhost:3306 +2. 数据库名称:testfb +3. 表名称:users +4. 字段:id, username, password, email, phone, created_at, updated_at +5. 密码字段需加密。 +## redis模块 +1. 存储用户的token信息 +2. redis地址:localhost:6379 + +## 路由信息 +1. 登录:POST /login +2. 获取当前用户信息: GET /user +3. 修改当前用户信息: PUT /user +4. 获取某个用户信息: GET /users/:id + +## 其他 +1. 日志保存在当前main.go目录下 \ No newline at end of file diff --git a/.history/handlers/handlers_20240925161943.go b/.history/handlers/handlers_20240925161943.go new file mode 100644 index 0000000..67d0276 --- /dev/null +++ b/.history/handlers/handlers_20240925161943.go @@ -0,0 +1,56 @@ +package handlers + +import ( + "strconv" + "time" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/storage/redis/v3" + "github.com/golang-jwt/jwt/v4" + "gorm.io/gorm" + + "testfb/models" +) + +func Login(db *gorm.DB, redisClient *redis.Storage) fiber.Handler { + return func(c *fiber.Ctx) error { + var input struct { + Username string `json:"username"` + Password string `json:"password"` + } + + if err := c.BodyParser(&input); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid input"}) + } + + var user models.User + if err := db.Where("username = ?", input.Username).First(&user).Error; err != nil { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"}) + } + + if err := user.ComparePassword(input.Password); err != nil { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"}) + } + + token := jwt.New(jwt.SigningMethodHS256) + claims := token.Claims.(jwt.MapClaims) + claims["user_id"] = user.ID + claims["exp"] = time.Now().Add(time.Hour * 24).Unix() + + t, err := token.SignedString([]byte("your-secret-key")) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not login"}) + } + + // Convert user.ID to string before storing in Redis + userIDStr := strconv.FormatUint(uint64(user.ID), 10) + err = redisClient.Set(t, []byte(userIDStr), 24*time.Hour) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not store token"}) + } + + return c.JSON(fiber.Map{"token": t}) + } +} + +// ... (rest of the file remains unchanged) diff --git a/.history/handlers/handlers_20240925162137.go b/.history/handlers/handlers_20240925162137.go new file mode 100644 index 0000000..e1876a9 --- /dev/null +++ b/.history/handlers/handlers_20240925162137.go @@ -0,0 +1,105 @@ +package handlers + +import ( + "strconv" + "time" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/storage/redis/v3" + "github.com/golang-jwt/jwt/v4" + "gorm.io/gorm" + + "testfb/models" +) + +func Login(db *gorm.DB, redisClient *redis.Storage) fiber.Handler { + return func(c *fiber.Ctx) error { + var input struct { + Username string `json:"username"` + Password string `json:"password"` + } + + if err := c.BodyParser(&input); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid input"}) + } + + var user models.User + if err := db.Where("username = ?", input.Username).First(&user).Error; err != nil { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"}) + } + + if err := user.ComparePassword(input.Password); err != nil { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"}) + } + + token := jwt.New(jwt.SigningMethodHS256) + claims := token.Claims.(jwt.MapClaims) + claims["user_id"] = user.ID + claims["exp"] = time.Now().Add(time.Hour * 24).Unix() + + t, err := token.SignedString([]byte("your-secret-key")) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not login"}) + } + + // Convert user.ID to string before storing in Redis + userIDStr := strconv.FormatUint(uint64(user.ID), 10) + err = redisClient.Set(t, []byte(userIDStr), 24*time.Hour) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not store token"}) + } + + return c.JSON(fiber.Map{"token": t}) + } +} + +func GetCurrentUser(db *gorm.DB) fiber.Handler { + return func(c *fiber.Ctx) error { + userID := c.Locals("user_id").(uint) + + var user models.User + if err := db.First(&user, userID).Error; err != nil { + return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"}) + } + + return c.JSON(user) + } +} + +func UpdateCurrentUser(db *gorm.DB) fiber.Handler { + return func(c *fiber.Ctx) error { + userID := c.Locals("user_id").(uint) + + var input models.User + if err := c.BodyParser(&input); err != nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid input"}) + } + + var user models.User + if err := db.First(&user, userID).Error; err != nil { + return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"}) + } + + user.Email = input.Email + user.Phone = input.Phone + + if err := db.Save(&user).Error; err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not update user"}) + } + + return c.JSON(user) + } +} + +func GetUserByID(db *gorm.DB) fiber.Handler { + return func(c *fiber.Ctx) error { + id := c.Params("id") + + var user models.User + if err := db.First(&user, id).Error; err != nil { + return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"}) + } + + return c.JSON(user) + } +} diff --git a/.history/middleware/auth_20240925162004.go b/.history/middleware/auth_20240925162004.go new file mode 100644 index 0000000..05242ac --- /dev/null +++ b/.history/middleware/auth_20240925162004.go @@ -0,0 +1,31 @@ +package middleware + +import ( + "strconv" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/storage/redis/v3" +) + +func AuthMiddleware(redisClient *redis.Storage) fiber.Handler { + return func(c *fiber.Ctx) error { + token := c.Get("Authorization") + if token == "" { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Missing authorization token"}) + } + + userIDBytes, err := redisClient.Get(token) + if err != nil { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid or expired token"}) + } + + userIDStr := string(userIDBytes) + userID, err := strconv.ParseUint(userIDStr, 10, 64) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Invalid user ID format"}) + } + + c.Locals("user_id", uint(userID)) + return c.Next() + } +} diff --git a/.history/middleware/auth_20240925162154.go b/.history/middleware/auth_20240925162154.go new file mode 100644 index 0000000..05242ac --- /dev/null +++ b/.history/middleware/auth_20240925162154.go @@ -0,0 +1,31 @@ +package middleware + +import ( + "strconv" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/storage/redis/v3" +) + +func AuthMiddleware(redisClient *redis.Storage) fiber.Handler { + return func(c *fiber.Ctx) error { + token := c.Get("Authorization") + if token == "" { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Missing authorization token"}) + } + + userIDBytes, err := redisClient.Get(token) + if err != nil { + return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid or expired token"}) + } + + userIDStr := string(userIDBytes) + userID, err := strconv.ParseUint(userIDStr, 10, 64) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Invalid user ID format"}) + } + + c.Locals("user_id", uint(userID)) + return c.Next() + } +} diff --git a/README.md b/README.md index 190a180..735a3bc 100644 --- a/README.md +++ b/README.md @@ -1 +1,31 @@ -123 +# TestFB +> 使用Go语言,实现用户登录、获取用户信息、修改用户信息。 + +## 工程要求:结构化工程,更加规范的代码编写。 +## 工程使用的模块或技术: +1. Go语言 +2. fiber框架 +3. Gorm ORM框架 +4. fiber下的storage/redis v3模块 +5. JWT身份验证,存储在redis中 +6. mysql,使用fiber下的storage/mysql v2模块 +7. 日志,使用fiber自带的日志模块 + +## mysql模块 +1. 数据库地址:localhost:3306 +2. 数据库名称:testfb +3. 表名称:users +4. 字段:id, username, password, email, phone, created_at, updated_at +5. 密码字段需加密。 +## redis模块 +1. 存储用户的token信息 +2. redis地址:localhost:6379 + +## 路由信息 +1. 登录:POST /login +2. 获取当前用户信息: GET /user +3. 修改当前用户信息: PUT /user +4. 获取某个用户信息: GET /users/:id + +## 其他 +1. 日志保存在当前main.go目录下 \ No newline at end of file diff --git a/handlers/handlers.go b/handlers/handlers.go index 7d3b47f..e1876a9 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -1,6 +1,7 @@ package handlers import ( + "strconv" "time" "github.com/gofiber/fiber/v2" @@ -41,7 +42,9 @@ func Login(db *gorm.DB, redisClient *redis.Storage) fiber.Handler { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not login"}) } - err = redisClient.Set(t, user.ID, 24*time.Hour) + // Convert user.ID to string before storing in Redis + userIDStr := strconv.FormatUint(uint64(user.ID), 10) + err = redisClient.Set(t, []byte(userIDStr), 24*time.Hour) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not store token"}) } diff --git a/middleware/auth.go b/middleware/auth.go index bc32fec..05242ac 100644 --- a/middleware/auth.go +++ b/middleware/auth.go @@ -1,6 +1,8 @@ package middleware import ( + "strconv" + "github.com/gofiber/fiber/v2" "github.com/gofiber/storage/redis/v3" ) @@ -12,12 +14,18 @@ func AuthMiddleware(redisClient *redis.Storage) fiber.Handler { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Missing authorization token"}) } - userID, err := redisClient.Get(token) + userIDBytes, err := redisClient.Get(token) if err != nil { return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid or expired token"}) } - c.Locals("user_id", userID) + userIDStr := string(userIDBytes) + userID, err := strconv.ParseUint(userIDStr, 10, 64) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Invalid user ID format"}) + } + + c.Locals("user_id", uint(userID)) return c.Next() } }