在 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()
}
}
代码说明:
- 数据库初始化:我们使用 SQLite 数据库来存储用户数据,并自动迁移
User
结构体到数据库。 - 用户注册:接收 JSON 输入,哈希密码并存储到数据库。
- 用户登录:检查用户名和密码,如果成功则返回登录成功的信息。
- 保护路由:提供一个受保护的路由,实际应用中应该添加真实的身份验证逻辑(如 JWT 验证)。
- 中间件:可以在其中实现对每个请求进行身份验证。
注意事项:
- 本示例中的授权机制非常基础。建议使用 JWT 或其他方法来管理会话和授权。
- 在生产环境中,请确保正确地处理错误和敏感信息。
- 使用 HTTPS 确保安全传输数据。
这个简单而优雅的结构为你整合了基本的用户认证链条,你可以根据自己的需求进一步扩展功能。
内容由零声教学AI助手提供,问题来源于学员提问