首页 AI前沿 Web开发 机器学习 深度学习 Go编程 Python编程 网络技术 区块链 时间序列 闲情逸致 我的网站

go开发gin web中的用户验证怎么实现?

在 Gin Web 应用中实现用户验证,常见的方式有基于令牌(Token)的验证和基于 Session - Cookie 的验证。以下分别介绍这两种方式的实现思路和代码示例:

基于令牌(Token)的验证

  1. 生成和验证 Token:通常使用 JWT(JSON Web Token)。JWT 由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
  2. 中间件验证:在 Gin 中通过中间件来验证请求中的 Token 是否有效。

示例代码

package main

import (
    "github.com/dgrijalva/jwt-go"
    "github.com/gin-gonic/gin"
    "net/http"
    "time"
)

// 定义 JWT 密钥
const jwtSecret = "your-secret-key"

// Claims 自定义载荷结构
type Claims struct {
    UserID uint `json:"user_id"`
    jwt.StandardClaims
}

// GenerateToken 生成 JWT
func GenerateToken(userID uint) (string, error) {
    expirationTime := time.Now().Add(5 * time.Minute)
    claims := &Claims{
        UserID: userID,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expirationTime.Unix(),
        },
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString([]byte(jwtSecret))
}

// VerifyToken 验证 JWT
func VerifyToken(tokenString string) (*Claims, bool) {
    claims := &Claims{}
    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
        return []byte(jwtSecret), nil
    })
    if err != nil ||!token.Valid {
        return nil, false
    }
    return claims, true
}

// AuthMiddleware 验证中间件
func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        tokenString := c.GetHeader("Authorization")
        if tokenString == "" {
            c.JSON(http.StatusUnauthorized, gin.H{"error": "未提供认证令牌"})
            c.Abort()
            return
        }
        tokenString = tokenString[len("Bearer "):]
        claims, ok := VerifyToken(tokenString)
        if!ok {
            c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的认证令牌"})
            c.Abort()
            return
        }
        c.Set("user_id", claims.UserID)
        c.Next()
    }
}

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

    r.POST("/login", func(c *gin.Context) {
        // 模拟登录验证
        var login struct {
            Username string `json:"username"`
            Password string `json:"password"`
        }
        if err := c.ShouldBindJSON(&login); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": "请求格式错误"})
            return
        }
        if login.Username == "admin" && login.Password == "password" {
            token, err := GenerateToken(1)
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": "生成令牌失败"})
                return
            }
            c.JSON(http.StatusOK, gin.H{"token": token})
        } else {
            c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
        }
    })

    r.GET("/protected", AuthMiddleware(), func(c *gin.Context) {
        userID := c.MustGet("user_id").(uint)
        c.JSON(http.StatusOK, gin.H{"message": "这是受保护的路由", "user_id": userID})
    })

    r.Run(":8080")
}
  1. 初始化 Session:使用 github.com/gorilla/sessions 库来管理会话。
  2. 登录时设置 Session:验证用户登录信息后,在 Session 中记录用户状态。
  3. 中间件验证 Session:通过中间件检查 Session 中用户是否已登录。

示例代码

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/gorilla/sessions"
    "net/http"
)

// 定义 Session 存储
var store = sessions.NewCookieStore([]byte("your-secret-key"))

// Login 处理登录请求
func Login(c *gin.Context) {
    var login struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    if err := c.ShouldBindJSON(&login); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "请求格式错误"})
        return
    }
    if login.Username == "admin" && login.Password == "password" {
        session, _ := store.Get(c.Request, "user-session")
        session.Values["is_logged_in"] = true
        session.Values["user_id"] = 1
        session.Save(c.Request, c.ResponseWriter)
        c.JSON(http.StatusOK, gin.H{"message": "登录成功"})
    } else {
        c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
    }
}

// AuthMiddleware 验证 Session 中间件
func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        session, err := store.Get(c.Request, "user-session")
        if err != nil {
            c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
            c.Abort()
            return
        }
        isLoggedIn := session.Values["is_logged_in"]
        if isLoggedIn != true {
            c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
            c.Abort()
            return
        }
        c.Next()
    }
}

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

    r.POST("/login", Login)

    r.GET("/protected", AuthMiddleware(), func(c *gin.Context) {
        session, _ := store.Get(c.Request, "user-session")
        userID := session.Values["user_id"]
        c.JSON(http.StatusOK, gin.H{"message": "这是受保护的路由", "user_id": userID})
    })

    r.Run(":8080")
}

以上两种方式各有优缺点,基于 Token 的方式适合无状态的分布式架构,而基于 Session - Cookie 的方式更适合传统的 Web 应用场景。你可以根据项目的具体需求来选择合适的方式。

posted @ 2025-08-14 19:02  gosamuel  阅读(33)  评论(0)    收藏  举报
© 2025 Woloveai | 版权所有 如有侵权,请联系删除。