update
This commit is contained in:
parent
5c2d928e40
commit
38f44d0556
@ -1 +0,0 @@
|
||||
123
|
||||
@ -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目录下
|
||||
@ -1,8 +0,0 @@
|
||||
package config
|
||||
|
||||
const (
|
||||
//日志文件路径
|
||||
LogFilePath = "testfb.log"
|
||||
//地址+端口
|
||||
Port = ":3030"
|
||||
)
|
||||
31
.history/config/config_20240925164512.go
Normal file
31
.history/config/config_20240925164512.go
Normal 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,
|
||||
})
|
||||
}
|
||||
31
.history/config/config_20240925164617.go
Normal file
31
.history/config/config_20240925164617.go
Normal 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,
|
||||
})
|
||||
}
|
||||
31
.history/config/config_20240925164750.go
Normal file
31
.history/config/config_20240925164750.go
Normal 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,
|
||||
})
|
||||
}
|
||||
33
.history/config/config_20240925164752.go
Normal file
33
.history/config/config_20240925164752.go
Normal 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,
|
||||
})
|
||||
}
|
||||
@ -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)
|
||||
@ -1,6 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"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"})
|
||||
}
|
||||
|
||||
// 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"})
|
||||
}
|
||||
@ -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"})
|
||||
}
|
||||
|
||||
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"})
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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"))
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
package middleware
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
@ -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"`
|
||||
}
|
||||
36
.history/models/user_20240925164429.go
Normal file
36
.history/models/user_20240925164429.go
Normal 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))
|
||||
}
|
||||
36
.history/models/user_20240925164519.go
Normal file
36
.history/models/user_20240925164519.go
Normal 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))
|
||||
}
|
||||
36
.history/models/user_20240925164536.go
Normal file
36
.history/models/user_20240925164536.go
Normal 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))
|
||||
}
|
||||
36
.history/models/user_20240925164547.go
Normal file
36
.history/models/user_20240925164547.go
Normal 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))
|
||||
}
|
||||
36
.history/models/user_20240925164556.go
Normal file
36
.history/models/user_20240925164556.go
Normal 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))
|
||||
}
|
||||
36
.history/models/user_20240925164558.go
Normal file
36
.history/models/user_20240925164558.go
Normal 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))
|
||||
}
|
||||
36
.history/models/user_20240925164614.go
Normal file
36
.history/models/user_20240925164614.go
Normal 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))
|
||||
}
|
||||
36
.history/models/user_20240925164759.go
Normal file
36
.history/models/user_20240925164759.go
Normal 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))
|
||||
}
|
||||
37
.history/models/user_20240925164817.go
Normal file
37
.history/models/user_20240925164817.go
Normal 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))
|
||||
}
|
||||
37
.history/models/user_20240925164826.go
Normal file
37
.history/models/user_20240925164826.go
Normal 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))
|
||||
}
|
||||
37
.history/models/user_20240925164931.go
Normal file
37
.history/models/user_20240925164931.go
Normal 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))
|
||||
}
|
||||
37
.history/models/user_20240925165047.go
Normal file
37
.history/models/user_20240925165047.go
Normal 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))
|
||||
}
|
||||
@ -27,5 +27,10 @@ func (u *User) BeforeCreate(tx *gorm.DB) 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))
|
||||
}
|
||||
36
.history/models/user_20240925165203.go
Normal file
36
.history/models/user_20240925165203.go
Normal 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))
|
||||
}
|
||||
}
|
||||
36
.history/models/user_20240925165204.go
Normal file
36
.history/models/user_20240925165204.go
Normal 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))
|
||||
}
|
||||
}
|
||||
@ -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",
|
||||
})
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
package storage
|
||||
@ -1 +0,0 @@
|
||||
package storage
|
||||
@ -1 +0,0 @@
|
||||
package storage
|
||||
@ -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"})
|
||||
}
|
||||
|
||||
// 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"})
|
||||
}
|
||||
|
||||
@ -27,5 +27,10 @@ func (u *User) BeforeCreate(tx *gorm.DB) error {
|
||||
}
|
||||
|
||||
func (u *User) ComparePassword(password string) error {
|
||||
return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
|
||||
//直接比较密码,不用bcrypt
|
||||
if u.Password == password {
|
||||
return nil
|
||||
} else {
|
||||
return bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user