极客时间初级Go工程师训练营

802 阅读2分钟

极客时间初级Go工程师训练营

核心代码,注释必读

// download:链接: https://pan.baidu.com/s/1_76lIW6L_nnDJ-hnOwZTJw?pwd=6zf2 提取码: 6zf2

Gin和GORM介绍

Gin是一个非常流行的Go语言Web框架,具有快速、高效和轻量级等特点。它可以帮助我们快速构建RESTful API或Web应用程序。

而GORM是一个Go语言的ORM库,它的目的是简化对SQL数据库的操作。它支持多种数据库(MySQL、PostgreSQL、SQLite等),可以通过结构体进行数据建模,提供了丰富的查询功能。

用户注册登录功能实现

功能需求

我们要实现一个用户注册登录功能,包括以下功能:

  • 用户注册:用户通过用户名和密码注册账号;
  • 用户登录:用户通过用户名和密码登录账号,如果登录成功则返回一个令牌(token);
  • 获取用户信息:用户通过令牌获取自己的信息。

数据模型设计

我们需要一个User数据模型来存储用户信息,包含以下字段:

  • ID:用户ID;
  • Username:用户名;
  • PasswordHash:密码哈希值。
type User struct {
    gorm.Model
    Username     string `gorm:"unique_index"`
    PasswordHash string
}

注册功能实现

用户注册是将用户名和密码存储到数据库中,我们需要这样做:

func Register(c *gin.Context) {
    var user User

    // 解析请求中的JSON数据到user变量中
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    // 如果用户名已经存在,则返回错误
    if db.Where("username = ?", user.Username).First(&User{}).Error == nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "username already exists"})
        return
    }

    // 将用户密码进行哈希
    passwordHash, err := bcrypt.GenerateFromPassword([]byte(user.PasswordHash), bcrypt.DefaultCost)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }
    user.PasswordHash = string(passwordHash)

    // 将用户保存到数据库中
    if err := db.Create(&user).Error; err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    // 返回成功信息
    c.JSON(http.StatusOK, gin.H{"message": "user created"})
}

上面代码中:

  • 我们使用ShouldBindJSON函数将请求中的JSON数据绑定到user变量上;
  • 我们使用db.Where函数查询是否已经存在相同的用户名;
  • 我们使用bcrypt库对密码进行哈希处理;
  • 我们使用db.Create函数将用户存储到数据库中;
  • 在最后,我们返回成功信息。

登录功能实现

用户登录是验证用户提供的用户名和密码是否与数据库中的相同。我们需要这样做:

func Login(c *gin.Context) {
    var user User

    // 解析请求中的JSON数据到user变量中
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    // 检查用户是否存在
    if db.Where("username = ?", user.Username).First(&user).Error != nil {
        c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid username or password"})
        return
    }

    // 检查密码是否正确
    if err := bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(user.PasswordHash)); err != nil {
        c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid username or password"})
        return
    }

    // 创建JWT令牌
    token := jwt.New(jwt.SigningMethodHS256)
    claims := token.Claims.(jwt.MapClaims)
    claims["user_id"] = user.ID
    claims["exp"] = time.Now().Add(time.Hour * 24).Unix()

    // 签名令牌并返回
    tokenString, err := token.SignedString([]byte("secret"))
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
        return
    }

    c.JSON(http.StatusOK, gin.H