This commit is contained in:
maxwell 2024-09-25 16:52:21 +08:00
parent 5c2d928e40
commit 38f44d0556
48 changed files with 652 additions and 468 deletions

View File

@ -1 +0,0 @@
123

View File

@ -1,31 +0,0 @@
# 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目录下

View File

@ -1,8 +0,0 @@
package config
const (
//日志文件路径
LogFilePath = "testfb.log"
//地址+端口
Port = ":3030"
)

View File

@ -0,0 +1,31 @@
package config
import (
"github.com/gofiber/storage/redis/v3"
)
type Config struct {
DBConnString string
RedisAddr string
JWTSecret string
ErrInvalidPassword string
}
func New() *Config {
return &Config{
DBConnString: "root:password@tcp(localhost:3306)/testfb?charset=utf8mb4&parseTime=True&loc=Local",
RedisAddr: "localhost:6379",
JWTSecret: "your-secret-key",
ErrInvalidPassword: "Invalid password",
}
}
func InitRedis(addr string) *redis.Storage {
return redis.New(redis.Config{
Host: addr,
Port: 6379,
Username: "",
Password: "",
Database: 0,
})
}

View File

@ -0,0 +1,31 @@
package config
import (
"github.com/gofiber/storage/redis/v3"
)
type Config struct {
DBConnString string
RedisAddr string
JWTSecret string
ErrInvalidPassword string
}
func New() *Config {
return &Config{
DBConnString: "root:password@tcp(localhost:3306)/testfb?charset=utf8mb4&parseTime=True&loc=Local",
RedisAddr: "localhost:6379",
JWTSecret: "your-secret-key",
ErrInvalidPassword: "Invalid password",
}
}
func InitRedis(addr string) *redis.Storage {
return redis.New(redis.Config{
Host: addr,
Port: 6379,
Username: "",
Password: "",
Database: 0,
})
}

View File

@ -0,0 +1,31 @@
package config
import (
"github.com/gofiber/storage/redis/v3"
)
const (
ErrInvalidPassword = "invalid password",
)
type Config struct {
DBConnString string
RedisAddr string
JWTSecret string
}
func New() *Config {
return &Config{
DBConnString: "root:password@tcp(localhost:3306)/testfb?charset=utf8mb4&parseTime=True&loc=Local",
RedisAddr: "localhost:6379",
JWTSecret: "your-secret-key",
}
}
func InitRedis(addr string) *redis.Storage {
return redis.New(redis.Config{
Host: addr,
Port: 6379,
Username: "",
Password: "",
Database: 0,
})
}

View File

@ -0,0 +1,33 @@
package config
import (
"github.com/gofiber/storage/redis/v3"
)
const (
ErrInvalidPassword = "invalid password"
)
type Config struct {
DBConnString string
RedisAddr string
JWTSecret string
}
func New() *Config {
return &Config{
DBConnString: "root:password@tcp(localhost:3306)/testfb?charset=utf8mb4&parseTime=True&loc=Local",
RedisAddr: "localhost:6379",
JWTSecret: "your-secret-key",
}
}
func InitRedis(addr string) *redis.Storage {
return redis.New(redis.Config{
Host: addr,
Port: 6379,
Username: "",
Password: "",
Database: 0,
})
}

View File

@ -1,56 +0,0 @@
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)

View File

@ -1,6 +1,7 @@
package handlers package handlers
import ( import (
"strconv"
"time" "time"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
@ -27,6 +28,7 @@ func Login(db *gorm.DB, redisClient *redis.Storage) fiber.Handler {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"}) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"})
} }
// if err := user.ComparePassword(input.Password); err != nil {
if err := user.ComparePassword(input.Password); err != nil { if err := user.ComparePassword(input.Password); err != nil {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"}) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"})
} }
@ -41,7 +43,9 @@ func Login(db *gorm.DB, redisClient *redis.Storage) fiber.Handler {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not login"}) 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 { if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not store token"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Could not store token"})
} }

View File

@ -1,35 +0,0 @@
package main
import (
"log"
"os"
"testfb/config"
"testfb/routes"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
)
func main() {
//创建日志文件
f, err := os.OpenFile(config.LogFilePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("日志文件创建失败:", err)
}
defer f.Close()
app := fiber.New()
app.Use(logger.New(logger.Config{
Output: f,
}))
//注册路由
routes.SetupRoutes(app)
// 启动服务
log.Println("服务启动成功,监听端口:", config.Port)
if err := app.Listen(config.Port); err != nil {
log.Fatalln("服务启动失败:", err)
}
}

View File

@ -1,61 +0,0 @@
package main
import (
"log"
"os"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"testfb/config"
"testfb/handlers"
"testfb/middleware"
"testfb/models"
)
func main() {
// Initialize configuration
cfg := config.New()
// Set up logging
logFile, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("Error opening log file: %v", err)
}
defer logFile.Close()
// Initialize database
db, err := gorm.Open(mysql.Open(cfg.DBConnString), &gorm.Config{})
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
// Auto-migrate the users table
err = db.AutoMigrate(&models.User{})
if err != nil {
log.Fatalf("Failed to auto-migrate: %v", err)
}
// Initialize Redis client
redisClient := config.InitRedis(cfg.RedisAddr)
// Create Fiber app
app := fiber.New()
// Set up middleware
app.Use(logger.New(logger.Config{
Format: "[${time}] ${status} - ${latency} ${method} ${path}\n",
Output: logFile,
}))
// Set up routes
app.Post("/login", handlers.Login(db, redisClient))
app.Get("/user", middleware.AuthMiddleware(redisClient), handlers.GetCurrentUser(db))
app.Put("/user", middleware.AuthMiddleware(redisClient), handlers.UpdateCurrentUser(db))
app.Get("/users/:id", middleware.AuthMiddleware(redisClient), handlers.GetUserByID(db))
// Start server
log.Fatal(app.Listen(":8080"))
}

View File

@ -1 +0,0 @@
package middleware

View File

@ -1,23 +0,0 @@
package middleware
import (
"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"})
}
userID, 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)
return c.Next()
}
}

View File

@ -1,23 +0,0 @@
package middleware
import (
"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"})
}
userID, 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)
return c.Next()
}
}

View File

@ -1,6 +0,0 @@
package models
type User struct {
Username string `json:"username" validate:"required,alphanum,min=3,max=20"`
Password string `json:"password" validate:"required,min=8,max=20"`
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,37 @@
package models
import (
. "testfb/config"
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,37 @@
package models
import (
. "testfb/config"
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
return ErrInvalidPassword
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,37 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
err := "Invalid password"
return err
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -0,0 +1,37 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password != password {
err := 123
return err
}
return nil
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}

View File

@ -27,5 +27,10 @@ func (u *User) BeforeCreate(tx *gorm.DB) error {
} }
func (u *User) ComparePassword(password string) error { func (u *User) ComparePassword(password string) error {
return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) //直接比较密码不用bcrypt
if u.Password == password {
return nil
}
// return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
} }

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password == password {
return nil
} else {
return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}
}

View File

@ -0,0 +1,36 @@
package models
import (
"time"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"unique" json:"username"`
Password string `json:"-"`
Email string `json:"email"`
Phone string `json:"phone"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (u *User) BeforeCreate(tx *gorm.DB) error {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
if err != nil {
return err
}
u.Password = string(hashedPassword)
return nil
}
func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password == password {
return nil
} else {
return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}
}

View File

@ -1,53 +0,0 @@
package routes
import (
"log"
"testfb/utils"
"github.com/gofiber/fiber/v2"
)
// 注册路由
func SetupRoutes(app *fiber.App) {
app.Post("/login", login)
}
// 处理登录
func login(c *fiber.Ctx) error {
//请求参数是JSON格式解析JSON数据
var data map[string]string
if err := c.BodyParser(&data); err != nil {
log.Println(err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid request",
})
}
//把JSON数据中的用户名和密码取出来
if data["username"] == "" || data["password"] == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid request",
})
}
username := data["username"]
password := data["password"]
log.Printf("Login request for user: %s", username)
log.Printf("Password: %s", password)
//验证用户名和密码
if utils.ValiddateUser(username, password) {
token, err := utils.GenerateJWT(username)
if err != nil {
log.Println(err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Cannot get token, Internal server error",
})
}
log.Println("Token generated for user:", username)
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"token": token,
})
}
log.Printf("Invalid username or password for user: %s", username)
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "Invalid username or password",
})
}

View File

@ -1,82 +0,0 @@
package routes
import (
"log"
"testfb/utils"
"github.com/gofiber/fiber/v2"
)
// 注册路由
func SetupRoutes(app *fiber.App) {
app.Post("/login", login)
}
// 处理登录
func login(c *fiber.Ctx) error {
//请求参数是JSON格式解析JSON数据
var data map[string]string
if err := c.BodyParser(&data); err != nil {
log.Println(err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid request",
})
}
//把JSON数据中的用户名和密码取出来
if data["username"] == "" || data["password"] == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid request",
})
}
username := data["username"]
password := data["password"]
log.Printf("Login request for user: %s", username)
log.Printf("Password: %s", password)
//验证用户名和密码
if utils.ValiddateUser(username, password) {
token, err := utils.GenerateJWT(username)
if err != nil {
log.Println(err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Cannot get token, Internal server error",
})
}
log.Println("Token generated for user:", username)
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"token": token,
})
}
log.Printf("Invalid username or password for user: %s", username)
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "Invalid username or password",
})
}
// 得到用户信息。GET /userInfo
// 验证token。GET /validateToken
func userInfo(c *fiber.Ctx) error {
// 从请求头中获取token
token := c.Get("Authorization")
if token == "" {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "Unauthorized",
})
}
// 验证token
username, err := utils.ValidateJWT(token)
if err != nil {
log.Println(err)
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "Unauthorized",
})
}
// 得到用户信息
user, err := utils.GetUser(username)
if err != nil {
log.Println(err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Internal server error",
})
}
return c.Status(fiber.StatusOK).JSON(user)
}

View File

@ -1,82 +0,0 @@
package routes
import (
"log"
"testfb/utils"
"github.com/gofiber/fiber/v2"
)
// 注册路由
func SetupRoutes(app *fiber.App) {
app.Post("/login", login)
}
// 处理登录
func login(c *fiber.Ctx) error {
//请求参数是JSON格式解析JSON数据
var data map[string]string
if err := c.BodyParser(&data); err != nil {
log.Println(err)
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid request",
})
}
//把JSON数据中的用户名和密码取出来
if data["username"] == "" || data["password"] == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"message": "Invalid request",
})
}
username := data["username"]
password := data["password"]
log.Printf("Login request for user: %s", username)
log.Printf("Password: %s", password)
//验证用户名和密码
if utils.ValiddateUser(username, password) {
token, err := utils.GenerateJWT(username)
if err != nil {
log.Println(err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Cannot get token, Internal server error",
})
}
log.Println("Token generated for user:", username)
return c.Status(fiber.StatusOK).JSON(fiber.Map{
"token": token,
})
}
log.Printf("Invalid username or password for user: %s", username)
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "Invalid username or password",
})
}
// 得到用户信息。GET /userInfo
// 验证token。GET /validateToken
func userInfo(c *fiber.Ctx) error {
// 从请求头中获取token
token := c.Get("Authorization")
if token == "" {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "Unauthorized",
})
}
// 验证token
username, err := utils.ValidateToken(token)
if err != nil {
log.Println(err)
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
"message": "Unauthorized",
})
}
// 得到用户信息
user, err := utils.GetUser(username)
if err != nil {
log.Println(err)
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"message": "Internal server error",
})
}
return c.Status(fiber.StatusOK).JSON(user)
}

View File

@ -1 +0,0 @@
package storage

View File

@ -1 +0,0 @@
package storage

View File

@ -1 +0,0 @@
package storage

View File

@ -28,6 +28,7 @@ func Login(db *gorm.DB, redisClient *redis.Storage) fiber.Handler {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"}) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"})
} }
// if err := user.ComparePassword(input.Password); err != nil {
if err := user.ComparePassword(input.Password); err != nil { if err := user.ComparePassword(input.Password); err != nil {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"}) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid credentials"})
} }

View File

@ -27,5 +27,10 @@ func (u *User) BeforeCreate(tx *gorm.DB) error {
} }
func (u *User) ComparePassword(password string) error { func (u *User) ComparePassword(password string) error {
//直接比较密码不用bcrypt
if u.Password == password {
return nil
} else {
return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
}
} }