ZBLOG

go 写用户认证的demo,如何将整个认证链整合起来,写出优雅的代码

在 Go 中实现用户认证的过程可以分为几个步骤。这里是一个简单的用户认证示例,包括注册、登录以及中间件来保护需要认证的路由。

我们将使用以下组件:

  • gin 框架来处理 HTTP 请求
  • gorm 作为 ORM 来与数据库交互(SQLite)
  • bcrypt 来进行密码哈希

首先,确保你已安装所需的包:

go get github.com/gin-gonic/gin
go get gorm.io/gorm
go get gorm.io/driver/sqlite
go get golang.org/x/crypto/bcrypt

接下来是完整的代码示例:

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/gin-gonic/gin"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

var db *gorm.DB

type User struct {
	ID       uint   `json:"id" gorm:"primaryKey"`
	Username string `json:"username"`
	Password string `json:"password"`
}

// 初始化数据库
func setupDatabase() {
	var err error
	db, err = gorm.Open(sqlite.Open("users.db"), &gorm.Config{})
	if err != nil {
		log.Fatal("Failed to connect to database")
	}

	db.AutoMigrate(&User{})
}

// 哈希密码
func hashPassword(password string) (string, error) {
	bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	return string(bytes), err
}

// 检查密码是否匹配
func checkPassword(hashedPwd, plainPwd string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(hashedPwd), []byte(plainPwd))
	return err == nil
}

// 注册用户
func register(c *gin.Context) {
	var user User

	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
		return
	}

	hashedPassword, _ := hashPassword(user.Password)
	user.Password = hashedPassword

	result := db.Create(&user)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not create user"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "User registered successfully!"})
}

// 登录用户并返回 token(简化版,不做 token 签发)
func login(c *gin.Context) {
	var user User

	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
		return
	}

	var existingUser User
	if result := db.Where("username = ?", user.Username).First(&existingUser); result.Error != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"})
        return 
    }

	if !checkPassword(existingUser.Password, user.Password) {
        c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid username or password"})
        return 
    }
    
	c.JSON(http.StatusOK, gin.H{"message": "Login successful!"})
}

// 受保护的路由示例,仅供演示用(无实际验证逻辑)
func protectedRoute(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"message": "This is a protected route!"})
}

func main() {
	r := gin.Default()
	setupDatabase()

	r.POST("/register", register)
	r.POST("/login", login)

	protected := r.Group("/protected")
	protected.Use(authMiddleware())
	protected.GET("/", protectedRoute)

	r.Run(":8080")
}

// 示例中间件,用于验证用户认证状态(未具体实现)
func authMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
        // 在这里通常会检查JWT或Session等方式,下面仅做示例处理。
        // 假设所有请求都通过验证,可以根据需要调整逻辑
        
        // 如果没有认证则直接返回401 Unauthorized响应。
        
        c.Next()
    }
}

代码说明:

  1. 数据库初始化:我们使用 SQLite 数据库来存储用户数据,并自动迁移 User 结构体到数据库。
  2. 用户注册:接收 JSON 输入,哈希密码并存储到数据库。
  3. 用户登录:检查用户名和密码,如果成功则返回登录成功的信息。
  4. 保护路由:提供一个受保护的路由,实际应用中应该添加真实的身份验证逻辑(如 JWT 验证)。
  5. 中间件:可以在其中实现对每个请求进行身份验证。

注意事项:

  • 本示例中的授权机制非常基础。建议使用 JWT 或其他方法来管理会话和授权。
  • 在生产环境中,请确保正确地处理错误和敏感信息。
  • 使用 HTTPS 确保安全传输数据。

这个简单而优雅的结构为你整合了基本的用户认证链条,你可以根据自己的需求进一步扩展功能。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=20424

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?