Skip to content

jwt

需要定义 Claims,这个 jwt.RegisteredClaims 很重要

go
type CustomClaims struct {
    UserID uint   `json:"user_id"`
    Email  string `json:"email"`
    jwt.RegisteredClaims
}

然后就是签发 token

go
var jwtSecret = []byte("your-secret-key")

func GenerateToken(userID uint, email string) (string, error) {

    claims := CustomClaims{
        UserID: userID,
        Email:  email,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 2)),
            IssuedAt:  jwt.NewNumericDate(time.Now()),
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    return token.SignedString(jwtSecret)
}

gin 中间件

go
func JWTAuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {

        authHeader := c.GetHeader("Authorization")
        if authHeader == "" {
            c.AbortWithStatusJSON(401, gin.H{"error": "missing token"})
            return
        }

        parts := strings.Split(authHeader, " ")
        if len(parts) != 2 || parts[0] != "Bearer" {
            c.AbortWithStatusJSON(401, gin.H{"error": "invalid token format"})
            return
        }

        tokenString := parts[1]

        token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
            return jwtSecret, nil
        })

        if err != nil || !token.Valid {
            c.AbortWithStatusJSON(401, gin.H{"error": "invalid token"})
            return
        }

        claims := token.Claims.(*CustomClaims)

        // 写入 context
        c.Set("userID", claims.UserID)
        c.Set("email", claims.Email)

        c.Next()
    }
}
go
r := gin.Default()

authGroup := r.Group("/api")
authGroup.Use(JWTAuthMiddleware())
{
    authGroup.GET("/profile", ProfileHandler)
}
go
func ProfileHandler(c *gin.Context) {
    userID, _ := c.Get("userID")

    c.JSON(200, gin.H{
        "user_id": userID,
    })
}